From 2e8ab382b61a4c91872cd5f868e2316f7d6c5be4 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 24 May 2023 15:17:10 +0100 Subject: [PATCH 01/59] squash --- .fantomasignore | 17 + FSharp.Profiles.props | 28 ++ VisualFSharp.sln | 15 + src/Compiler/AbstractIL/ilread.fs | 4 +- src/Compiler/Checking/CheckExpressions.fs | 72 ++- src/Compiler/Checking/CheckPatterns.fs | 2 + src/Compiler/Checking/ConstraintSolver.fs | 444 +++++++++++++++--- src/Compiler/Checking/ConstraintSolver.fsi | 24 + src/Compiler/Checking/InfoReader.fs | 8 +- src/Compiler/Checking/MethodCalls.fs | 10 +- src/Compiler/Checking/NameResolution.fs | 4 +- src/Compiler/Checking/NicePrint.fs | 17 +- src/Compiler/Checking/PostInferenceChecks.fs | 28 +- src/Compiler/Checking/SignatureConformance.fs | 2 +- src/Compiler/Checking/TypeHierarchy.fs | 13 +- src/Compiler/Checking/TypeRelations.fs | 4 +- src/Compiler/Checking/import.fs | 38 +- src/Compiler/Checking/infos.fs | 10 +- .../DependencyManager/DependencyProvider.fs | 2 + .../DependencyManager/DependencyProvider.fsi | 2 + src/Compiler/Driver/CompilerConfig.fs | 10 +- src/Compiler/Driver/CompilerConfig.fsi | 10 +- src/Compiler/Driver/CompilerDiagnostics.fs | 56 ++- src/Compiler/Driver/CompilerImports.fs | 323 ++++++++----- src/Compiler/Driver/CompilerImports.fsi | 9 +- src/Compiler/Driver/CompilerOptions.fs | 8 + .../GraphChecking/FileContentMapping.fs | 3 + src/Compiler/Driver/StaticLinking.fs | 6 +- src/Compiler/FSComp.txt | 16 + src/Compiler/FSStrings.resx | 18 + src/Compiler/FSharp.Compiler.Service.fsproj | 3 +- src/Compiler/Facilities/LanguageFeatures.fs | 3 + src/Compiler/Facilities/LanguageFeatures.fsi | 1 + src/Compiler/Interactive/fsi.fs | 4 +- .../Legacy/LegacyHostedCompilerForTesting.fs | 12 +- src/Compiler/Service/IncrementalBuild.fs | 4 +- src/Compiler/Service/QuickParse.fs | 2 +- .../Service/ServiceDeclarationLists.fs | 2 +- src/Compiler/Service/ServiceLexing.fs | 3 + .../Service/ServiceParamInfoLocations.fs | 1 + src/Compiler/Service/ServiceParseTreeWalk.fs | 2 + src/Compiler/Service/ServiceParsedInputOps.fs | 6 + src/Compiler/Symbols/Symbols.fs | 22 + src/Compiler/Symbols/Symbols.fsi | 6 + src/Compiler/SyntaxTree/LexFilter.fs | 4 + src/Compiler/SyntaxTree/LexHelpers.fs | 4 + src/Compiler/SyntaxTree/PrettyNaming.fs | 9 + src/Compiler/SyntaxTree/PrettyNaming.fsi | 8 + src/Compiler/SyntaxTree/SyntaxTree.fs | 9 + src/Compiler/SyntaxTree/SyntaxTree.fsi | 8 + src/Compiler/TypedTree/TcGlobals.fs | 88 ++-- src/Compiler/TypedTree/TypeProviders.fs | 367 ++++++++++----- src/Compiler/TypedTree/TypeProviders.fsi | 94 ++-- src/Compiler/TypedTree/TypedTree.fs | 118 +++-- src/Compiler/TypedTree/TypedTree.fsi | 41 +- src/Compiler/TypedTree/TypedTreeBasics.fs | 85 +++- src/Compiler/TypedTree/TypedTreeBasics.fsi | 18 +- src/Compiler/TypedTree/TypedTreeOps.fs | 195 +++++--- src/Compiler/TypedTree/TypedTreeOps.fsi | 14 +- src/Compiler/TypedTree/TypedTreePickle.fs | 236 ++++++++-- src/Compiler/TypedTree/TypedTreePickle.fsi | 3 +- src/Compiler/TypedTree/tainted.fs | 12 +- src/Compiler/TypedTree/tainted.fsi | 6 +- src/Compiler/Utilities/illib.fs | 12 +- src/Compiler/Utilities/illib.fsi | 6 + src/Compiler/Utilities/lib.fs | 8 +- src/Compiler/Utilities/lib.fsi | 14 +- src/Compiler/Utilities/sformat.fs | 36 +- src/Compiler/pars.fsy | 55 ++- src/Compiler/xlf/FSComp.txt.cs.xlf | 60 +++ src/Compiler/xlf/FSComp.txt.de.xlf | 60 +++ src/Compiler/xlf/FSComp.txt.es.xlf | 60 +++ src/Compiler/xlf/FSComp.txt.fr.xlf | 60 +++ src/Compiler/xlf/FSComp.txt.it.xlf | 60 +++ src/Compiler/xlf/FSComp.txt.ja.xlf | 60 +++ src/Compiler/xlf/FSComp.txt.ko.xlf | 60 +++ src/Compiler/xlf/FSComp.txt.pl.xlf | 60 +++ src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 60 +++ src/Compiler/xlf/FSComp.txt.ru.xlf | 60 +++ src/Compiler/xlf/FSComp.txt.tr.xlf | 60 +++ src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 60 +++ src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 60 +++ src/Compiler/xlf/FSStrings.cs.xlf | 30 ++ src/Compiler/xlf/FSStrings.de.xlf | 30 ++ src/Compiler/xlf/FSStrings.es.xlf | 30 ++ src/Compiler/xlf/FSStrings.fr.xlf | 30 ++ src/Compiler/xlf/FSStrings.it.xlf | 30 ++ src/Compiler/xlf/FSStrings.ja.xlf | 30 ++ src/Compiler/xlf/FSStrings.ko.xlf | 30 ++ src/Compiler/xlf/FSStrings.pl.xlf | 30 ++ src/Compiler/xlf/FSStrings.pt-BR.xlf | 30 ++ src/Compiler/xlf/FSStrings.ru.xlf | 30 ++ src/Compiler/xlf/FSStrings.tr.xlf | 30 ++ src/Compiler/xlf/FSStrings.zh-Hans.xlf | 30 ++ src/Compiler/xlf/FSStrings.zh-Hant.xlf | 30 ++ src/FSharp.Build/FSharp.Build.fsproj | 3 +- src/FSharp.Build/FSharpCommandLineBuilder.fs | 9 +- src/FSharp.Build/Fsc.fs | 17 +- src/FSharp.Build/SubstituteText.fs | 2 +- src/FSharp.Core/FSharp.Core.fsproj | 1 - src/FSharp.Core/array.fs | 13 + src/FSharp.Core/async.fs | 4 + src/FSharp.Core/local.fs | 4 + src/FSharp.Core/option.fs | 28 ++ src/FSharp.Core/option.fsi | 28 +- src/FSharp.Core/prim-types.fs | 72 ++- src/FSharp.Core/prim-types.fsi | 118 ++++- src/fsi/console.fs | 32 +- .../Expressions/BindingExpressions/in05.fs | 4 +- .../ErrorMessages/TypeEqualsMissingTests.fs | 24 +- ...ervice.SurfaceArea.netstandard20.debug.bsl | 33 +- .../Microsoft.FSharp.Core/BigIntType.fs | 2 +- .../Microsoft.FSharp.Core/OptionModule.fs | 4 +- .../NullableOptionalRegressionTests.fs | 3 +- tests/fsharp/tests.fs | 88 +++- ...n_return_type_and_known_type_arguments.fsx | 6 +- tests/fsharp/typecheck/sigs/neg04.bsl | 4 +- tests/fsharp/typecheck/sigs/neg20.bsl | 6 +- vsintegration/src/FSharp.VS.FSI/fsiBasis.fs | 5 +- 119 files changed, 3722 insertions(+), 682 deletions(-) diff --git a/.fantomasignore b/.fantomasignore index 45eb387fa16..ea5d5fb913c 100644 --- a/.fantomasignore +++ b/.fantomasignore @@ -90,6 +90,23 @@ src/FSharp.Core/Query.fs src/FSharp.Core/seqcore.fs +# fsharp (to investigate) + +**/TypeProviders.fsi +**/tainted.fsi + +# uses nullness features + +**/DependencyProvider.fsi +src/FSharp.Core/array.fs +src/FSharp.Core/option.fsi +src/FSharp.Core/option.fs +src/fsi/console.fs +src/FSharp.Build/FSharpCommandLineBuilder.fs +src/Compiler/Utilities/sformat.fs +src/Compiler/Utilities/illib.fsi +src/Compiler/Utilities/illib.fs + # Fantomas limitations on implementation files (to investigate) src/Compiler/AbstractIL/ilwrite.fs diff --git a/FSharp.Profiles.props b/FSharp.Profiles.props index 66e46a32b08..d477f570f34 100644 --- a/FSharp.Profiles.props +++ b/FSharp.Profiles.props @@ -1,6 +1,34 @@ + + + false + + + + + false + + + + BUILDING_WITH_LKG;NO_NULLCHECKING_LIB_SUPPORT;$(DefineConstants) + false + + + + $(OtherFlags) /langversion:preview + + + + $(OtherFlags) /checknulls + + + + + $(NoWarn);3271 + NO_CHECKNULLS;$(DefineConstants) + diff --git a/VisualFSharp.sln b/VisualFSharp.sln index b7b9e82b5dc..516513595da 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -195,6 +195,8 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Editor.Tests", "vsin EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FSharp.Editor.IntegrationTests", "vsintegration\tests\FSharp.Editor.IntegrationTests\FSharp.Editor.IntegrationTests.csproj", "{E31F9B59-FCF1-4D04-8762-C7BB60285A7B}" EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "nullness", "tests\fsharp\core\nullness\nullness.fsproj", "{6992D926-AB1C-4CD4-94D5-0319D14DB54B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1033,6 +1035,18 @@ Global {E31F9B59-FCF1-4D04-8762-C7BB60285A7B}.Release|Any CPU.Build.0 = Release|Any CPU {E31F9B59-FCF1-4D04-8762-C7BB60285A7B}.Release|x86.ActiveCfg = Release|Any CPU {E31F9B59-FCF1-4D04-8762-C7BB60285A7B}.Release|x86.Build.0 = Release|Any CPU + {6992D926-AB1C-4CD4-94D5-0319D14DB54B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6992D926-AB1C-4CD4-94D5-0319D14DB54B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6992D926-AB1C-4CD4-94D5-0319D14DB54B}.Debug|x86.ActiveCfg = Debug|Any CPU + {6992D926-AB1C-4CD4-94D5-0319D14DB54B}.Debug|x86.Build.0 = Debug|Any CPU + {6992D926-AB1C-4CD4-94D5-0319D14DB54B}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {6992D926-AB1C-4CD4-94D5-0319D14DB54B}.Proto|Any CPU.Build.0 = Debug|Any CPU + {6992D926-AB1C-4CD4-94D5-0319D14DB54B}.Proto|x86.ActiveCfg = Debug|Any CPU + {6992D926-AB1C-4CD4-94D5-0319D14DB54B}.Proto|x86.Build.0 = Debug|Any CPU + {6992D926-AB1C-4CD4-94D5-0319D14DB54B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6992D926-AB1C-4CD4-94D5-0319D14DB54B}.Release|Any CPU.Build.0 = Release|Any CPU + {6992D926-AB1C-4CD4-94D5-0319D14DB54B}.Release|x86.ActiveCfg = Release|Any CPU + {6992D926-AB1C-4CD4-94D5-0319D14DB54B}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1114,6 +1128,7 @@ Global {FE23BB65-276A-4E41-8CC7-F7752241DEBA} = {39CDF34B-FB23-49AE-AB27-0975DA379BB5} {CBC96CC7-65AB-46EA-A82E-F6A788DABF80} = {F7876C9B-FB6A-4EFB-B058-D6967DB75FB2} {E31F9B59-FCF1-4D04-8762-C7BB60285A7B} = {F7876C9B-FB6A-4EFB-B058-D6967DB75FB2} + {6992D926-AB1C-4CD4-94D5-0319D14DB54B} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {48EDBBBE-C8EE-4E3C-8B19-97184A487B37} diff --git a/src/Compiler/AbstractIL/ilread.fs b/src/Compiler/AbstractIL/ilread.fs index 10189157adf..9f2f7d48f28 100644 --- a/src/Compiler/AbstractIL/ilread.fs +++ b/src/Compiler/AbstractIL/ilread.fs @@ -931,7 +931,7 @@ let mkCacheInt32 lowMem _inbase _nm _sz = if lowMem then (fun f x -> f x) else - let mutable cache = null + let mutable cache: ConcurrentDictionary MaybeNull = null // TODO NULLNESS: this explicit annotation should not be needed let mutable count = 0 #if STATISTICS addReport (fun oc -> @@ -960,7 +960,7 @@ let mkCacheGeneric lowMem _inbase _nm _sz = if lowMem then (fun f x -> f x) else - let mutable cache = null + let mutable cache: ConcurrentDictionary<_, _> MaybeNull = null // TODO NULLNESS: this explicit annotation should not be needed let mutable count = 0 #if STATISTICS addReport (fun oc -> diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 13075a5e6b9..666c8acc1a9 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -971,6 +971,43 @@ let TranslatePartialValReprInfo tps (PrelimValReprInfo (argsData, retData)) = // Members //------------------------------------------------------------------------- +let TcAddNullnessToType (warn: bool) (cenv: cenv) (env: TcEnv) nullness innerTyC m = + let g = cenv.g + if g.langFeatureNullness then + if TypeNullNever g innerTyC then + let tyString = NicePrint.minimalStringOfType env.DisplayEnv innerTyC + errorR(Error(FSComp.SR.tcTypeDoesNotHaveAnyNull(tyString), m)) + + match tryAddNullnessToTy nullness innerTyC with + + | None -> + let tyString = NicePrint.minimalStringOfType env.DisplayEnv innerTyC + errorR(Error(FSComp.SR.tcTypeDoesNotHaveAnyNull(tyString), m)) + innerTyC + + | Some innerTyCWithNull -> + // The inner type is not allowed to support null or use null as a representation value. + // For example "int option?" is not allowed, nor "string??". + // + // For variable types in FSharp.Core we make an exception because we must allow + // val toObj: value: 'T option -> 'T __withnull when 'T : not struct (* and 'T : __notnull *) + // wihout implying 'T is not null. This is because it is legitimate to use this + // function to "collapse" null and obj-null-coming-from-option using such a function. + + if not g.compilingFSharpCore || not (isTyparTy g innerTyC) then + AddCxTypeDefnNotSupportsNull env.DisplayEnv cenv.css m NoTrace innerTyC + + innerTyCWithNull + + else + if warn then + warning(Error(FSComp.SR.tcNullnessCheckingNotEnabled(), m)) + innerTyC + +//------------------------------------------------------------------------- +// Members +//------------------------------------------------------------------------- + let ComputeLogicalName (id: Ident) (memberFlags: SynMemberFlags) = match memberFlags.MemberKind with | SynMemberKind.ClassConstructor -> ".cctor" @@ -2085,7 +2122,7 @@ module GeneralizationHelpers = match tp.Constraints |> List.partition (function TyparConstraint.CoercesTo _ -> true | _ -> false) with | [TyparConstraint.CoercesTo(tgtTy, _)], others -> // Throw away null constraints if they are implied - if others |> List.exists (function TyparConstraint.SupportsNull _ -> not (TypeSatisfiesNullConstraint g m tgtTy) | _ -> true) + if others |> List.exists (function TyparConstraint.SupportsNull _ -> not (TypeNullIsExtraValue g m tgtTy) | _ -> true) then None else Some tgtTy | _ -> None @@ -3963,7 +4000,14 @@ let rec TcTyparConstraint ridx (cenv: cenv) newOk checkConstraints occ (env: TcE tpenv | SynTypeConstraint.WhereTyparSupportsNull(tp, m) -> - TcSimpleTyparConstraint cenv env newOk tpenv tp m AddCxTypeUseSupportsNull + TcSimpleTyparConstraint cenv env newOk tpenv tp m AddCxTypeDefnSupportsNull + + | SynTypeConstraint.WhereTyparNotSupportsNull(tp, m) -> + if g.langFeatureNullness then + TcSimpleTyparConstraint cenv env newOk tpenv tp m AddCxTypeDefnNotSupportsNull + else + warning(Error(FSComp.SR.tcNullnessCheckingNotEnabled(), m)) + tpenv | SynTypeConstraint.WhereTyparIsComparable(tp, m) -> TcSimpleTyparConstraint cenv env newOk tpenv tp m AddCxTypeMustSupportComparison @@ -4377,11 +4421,18 @@ and TcTypeOrMeasure kindOpt (cenv: cenv) newOk checkConstraints occ (iwsam: Warn | SynType.StaticConstant (synConst, m) -> TcTypeStaticConstant kindOpt tpenv synConst m + | SynType.StaticConstantNull m | SynType.StaticConstantNamed (_, _, m) | SynType.StaticConstantExpr (_, m) -> errorR(Error(FSComp.SR.parsInvalidLiteralInType(), m)) NewErrorType (), tpenv + | SynType.WithNull(innerTy, ambivalent, m) -> + let innerTyC, tpenv = TcTypeAndRecover cenv newOk checkConstraints occ WarnOnIWSAM.Yes env tpenv innerTy + let nullness = if ambivalent then KnownAmbivalentToNull else KnownWithNull + let tyWithNull = TcAddNullnessToType false cenv env nullness innerTyC m + tyWithNull, tpenv + | SynType.MeasurePower(ty, exponent, m) -> TcTypeMeasurePower kindOpt cenv newOk checkConstraints occ env tpenv ty exponent m @@ -4531,7 +4582,7 @@ and TcFunctionType (cenv: cenv) newOk checkConstraints occ env tpenv domainTy re and TcArrayType (cenv: cenv) newOk checkConstraints occ env tpenv rank elemTy m = let g = cenv.g let elemTy, tpenv = TcTypeAndRecover cenv newOk checkConstraints occ WarnOnIWSAM.Yes env tpenv elemTy - let tyR = mkArrayTy g rank elemTy m + let tyR = mkArrayTy g rank g.knownWithoutNull elemTy m tyR, tpenv and TcTypeParameter kindOpt (cenv: cenv) env newOk tpenv tp = @@ -4556,8 +4607,9 @@ and TcTypeWithConstraints (cenv: cenv) env newOk checkConstraints occ tpenv synT and TcTypeHashConstraint (cenv: cenv) env newOk checkConstraints occ tpenv synTy m = let tp = TcAnonTypeOrMeasure (Some TyparKind.Type) cenv TyparRigidity.WarnIfNotRigid TyparDynamicReq.Yes newOk m let ty, tpenv = TcTypeAndRecover cenv newOk checkConstraints occ WarnOnIWSAM.No env tpenv synTy - AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace ty (mkTyparTy tp) - tp.AsType, tpenv + let tpTy = mkTyparTy tp + AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace ty tpTy + tpTy, tpenv and TcTypeStaticConstant kindOpt tpenv c m = match c, kindOpt with @@ -4711,7 +4763,7 @@ and TcStaticConstantParameter (cenv: cenv) (env: TcEnv) tpenv kind (StripParenTy | SynConst.Double n when typeEquiv g g.float_ty kind -> record(g.float_ty); box (n: double) | SynConst.Char n when typeEquiv g g.char_ty kind -> record(g.char_ty); box (n: char) | SynConst.String (s, _, _) - | SynConst.SourceIdentifier (_, s, _) when s <> null && typeEquiv g g.string_ty kind -> record(g.string_ty); box (s: string) + | SynConst.SourceIdentifier (_, s, _) when typeEquiv g g.string_ty kind -> record(g.string_ty); box (s: string) | SynConst.Bool b when typeEquiv g g.bool_ty kind -> record(g.bool_ty); box (b: bool) | _ -> fail() v, tpenv @@ -4740,7 +4792,6 @@ and TcStaticConstantParameter (cenv: cenv) (env: TcEnv) tpenv kind (StripParenTy | Const.Single n -> record(g.float32_ty); box (n: single) | Const.Double n -> record(g.float_ty); box (n: double) | Const.Char n -> record(g.char_ty); box (n: char) - | Const.String null -> fail() | Const.String s -> record(g.string_ty); box (s: string) | Const.Bool b -> record(g.bool_ty); box (b: bool) | _ -> fail() @@ -4909,7 +4960,7 @@ and TcTypeApp (cenv: cenv) newOk checkConstraints occ env tpenv m tcref pathType List.iter2 (UnifyTypes cenv env m) tinst actualArgTys // Try to decode System.Tuple --> F# tuple types etc. - let ty = g.decompileType tcref actualArgTys + let ty = g.decompileType tcref actualArgTys g.knownWithoutNull ty, tpenv @@ -5564,8 +5615,11 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE | SynExpr.Null m -> TcNonControlFlowExpr env <| fun env -> + // Which? AddCxTypeUseSupportsNull env.DisplayEnv cenv.css m NoTrace overallTy.Commit - mkNull m overallTy.Commit, tpenv + //AddCxTypeDefnSupportsNull env.DisplayEnv cenv.css m NoTrace overallTy.Commit + let tyWithNull = addNullnessToTy KnownWithNull overallTy.Commit + mkNull m tyWithNull, tpenv | SynExpr.Lazy (synInnerExpr, m) -> TcNonControlFlowExpr env <| fun env -> diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index 5ce9fa02e69..2c28dfb5110 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -461,6 +461,8 @@ and TcRecordPat warnOnUpper cenv env vFlags patEnv ty fieldPats m = and TcNullPat cenv env patEnv ty m = try AddCxTypeUseSupportsNull env.DisplayEnv cenv.css m NoTrace ty + // Which? + //AddCxTypeDefnSupportsNull env.DisplayEnv cenv.css m NoTrace ty with exn -> errorRecovery exn m (fun _ -> TPat_null m), patEnv diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index 22ebc3ca4df..2cd52880800 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -69,6 +69,10 @@ open FSharp.Compiler.TypedTreeOps open FSharp.Compiler.TypeHierarchy open FSharp.Compiler.TypeRelations +#if !NO_TYPEPROVIDERS +open FSharp.Compiler.TypeProviders +#endif + //------------------------------------------------------------------------- // Generate type variables and record them in within the scope of the // compilation environment, which currently corresponds to the scope @@ -98,9 +102,10 @@ let NewErrorMeasureVar () = NewCompGenTypar (TyparKind.Measure, TyparRigidity.Flexible, TyparStaticReq.None, TyparDynamicReq.No, true) let NewInferenceType (g: TcGlobals) = - ignore g // included for future, minimizing code diffs, see https://github.com/dotnet/fsharp/pull/6804 - mkTyparTy (Construct.NewTypar (TyparKind.Type, TyparRigidity.Flexible, SynTypar(compgenId, TyparStaticReq.None, true), false, TyparDynamicReq.No, [], false, false)) - + let tp = Construct.NewTypar (TyparKind.Type, TyparRigidity.Flexible, SynTypar(compgenId, TyparStaticReq.None, true), false, TyparDynamicReq.No, [], false, false) + let nullness = if g.langFeatureNullness then NewNullnessVar() else KnownAmbivalentToNull + TType_var (tp, nullness) + let NewErrorType () = mkTyparTy (NewErrorTypar ()) @@ -240,7 +245,15 @@ exception ConstraintSolverTypesNotInEqualityRelation of displayEnv: DisplayEnv * exception ConstraintSolverTypesNotInSubsumptionRelation of displayEnv: DisplayEnv * argTy: TType * paramTy: TType * callRange: range * parameterRange: range -exception ConstraintSolverMissingConstraint of displayEnv: DisplayEnv * Typar * TyparConstraint * range * range +exception ConstraintSolverMissingConstraint of displayEnv: DisplayEnv * Typar * TyparConstraint * range * range + +exception ConstraintSolverNullnessWarningEquivWithTypes of DisplayEnv * TType * TType * NullnessInfo * NullnessInfo * range * range + +exception ConstraintSolverNullnessWarningWithTypes of DisplayEnv * TType * TType * NullnessInfo * NullnessInfo * range * range + +exception ConstraintSolverNullnessWarningWithType of DisplayEnv * TType * NullnessInfo * range * range + +exception ConstraintSolverNonNullnessWarningWithType of DisplayEnv * TType * NullnessInfo * range * range exception ConstraintSolverError of string * range * range @@ -1043,7 +1056,8 @@ and SolveTypMeetsTyparConstraints (csenv: ConstraintSolverEnv) ndeep m2 trace ty | ValueSome destTypar -> AddConstraint csenv ndeep m2 trace destTypar (TyparConstraint.DefaultsTo(priority, dty, m)) - | TyparConstraint.SupportsNull m2 -> SolveTypeUseSupportsNull csenv ndeep m2 trace ty + | TyparConstraint.NotSupportsNull m2 -> SolveTypeDefnNotSupportsNull csenv ndeep m2 trace ty + | TyparConstraint.SupportsNull m2 -> SolveTypeDefnSupportsNull csenv ndeep m2 trace ty | TyparConstraint.IsEnum(underlyingTy, m2) -> SolveTypeIsEnum csenv ndeep m2 trace ty underlyingTy | TyparConstraint.SupportsComparison(m2) -> SolveTypeSupportsComparison csenv ndeep m2 trace ty | TyparConstraint.SupportsEquality(m2) -> SolveTypeSupportsEquality csenv ndeep m2 trace ty @@ -1058,6 +1072,73 @@ and SolveTypMeetsTyparConstraints (csenv: ConstraintSolverEnv) ndeep m2 trace ty SolveMemberConstraint csenv false PermitWeakResolution.No ndeep m2 trace traitInfo |> OperationResult.ignore } +// nullness1: actual +// nullness2: expected +and SolveNullnessEquiv (csenv:ConstraintSolverEnv) m2 (trace: OptionalTrace) ty1 ty2 nullness1 nullness2 = + match nullness1, nullness2 with + | Nullness.Variable nv1, Nullness.Variable nv2 when nv1 === nv2 -> + CompleteD + | Nullness.Variable nv1, _ when nv1.IsSolved -> + SolveNullnessEquiv csenv m2 trace ty1 ty2 nv1.Solution nullness2 + | _, Nullness.Variable nv2 when nv2.IsSolved -> + SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nv2.Solution + | Nullness.Variable nv1, _ -> + trace.Exec (fun () -> nv1.Set nullness2) (fun () -> nv1.Unset()) + CompleteD + | _, Nullness.Variable nv2 -> + trace.Exec (fun () -> nv2.Set nullness1) (fun () -> nv2.Unset()) + CompleteD + | Nullness.Known n1, Nullness.Known n2 -> + match n1, n2 with + | NullnessInfo.AmbivalentToNull, _ -> CompleteD + | _, NullnessInfo.AmbivalentToNull -> CompleteD + | NullnessInfo.WithNull, NullnessInfo.WithNull -> CompleteD + | NullnessInfo.WithoutNull, NullnessInfo.WithoutNull -> CompleteD + // Allow expected of WithNull and actual of WithoutNull + // TODO NULLNESS: this is not sound in contravariant cases etc. + | NullnessInfo.WithNull, NullnessInfo.WithoutNull -> CompleteD + | _ -> + // NOTE: we never give nullness warnings for the 'obj' type + if csenv.g.checkNullness then + if not (isObjTy csenv.g ty1) && not (isObjTy csenv.g ty2) then + WarnD(ConstraintSolverNullnessWarningEquivWithTypes(csenv.DisplayEnv, ty1, ty2, n1, n2, csenv.m, m2)) + else + CompleteD + else + CompleteD + +// nullness1: target +// nullness2: source +and SolveNullnessSubsumesNullness (csenv:ConstraintSolverEnv) m2 (trace: OptionalTrace) ty1 ty2 nullness1 nullness2 = + match nullness1, nullness2 with + | Nullness.Variable nv1, Nullness.Variable nv2 when nv1 === nv2 -> + CompleteD + | Nullness.Variable nv1, _ when nv1.IsSolved -> + SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 nv1.Solution nullness2 + | _, Nullness.Variable nv2 when nv2.IsSolved -> + SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 nullness1 nv2.Solution + | Nullness.Variable nv1, _ -> + trace.Exec (fun () -> nv1.Set nullness2) (fun () -> nv1.Unset()) + CompleteD + | _, Nullness.Variable nv2 -> + trace.Exec (fun () -> nv2.Set nullness1) (fun () -> nv2.Unset()) + CompleteD + | Nullness.Known n1, Nullness.Known n2 -> + match n1, n2 with + | NullnessInfo.AmbivalentToNull, _ -> CompleteD + | _, NullnessInfo.AmbivalentToNull -> CompleteD + | NullnessInfo.WithNull, NullnessInfo.WithNull -> CompleteD + | NullnessInfo.WithoutNull, NullnessInfo.WithoutNull -> CompleteD + // Allow target of WithNull and actual of WithoutNull + | NullnessInfo.WithNull, NullnessInfo.WithoutNull -> CompleteD + | NullnessInfo.WithoutNull, NullnessInfo.WithNull -> + if csenv.g.checkNullness then + if not (isObjTy csenv.g ty1) && not (isObjTy csenv.g ty2) then + WarnD(ConstraintSolverNullnessWarningWithTypes(csenv.DisplayEnv, ty1, ty2, n1, n2, csenv.m, m2)) + else + CompleteD + else + CompleteD and SolveTyparEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) ty1 ty = trackErrors { let m = csenv.m @@ -1079,7 +1160,6 @@ and SolveTyparsEqualTypes (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optional SolveTyparEqualsTypePart1 csenv m2 trace tpTy r ty | _ -> failwith "SolveTyparsEqualTypes") - do! (tpTys, tys) ||> Iterate2D (fun tpTy ty -> match tpTy with | TType_var (r, _) @@ -1128,7 +1208,7 @@ and SolveAnonInfoEqualsAnonInfo (csenv: ConstraintSolverEnv) m2 (anonInfo1: Anon /// 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 = +and SolveTypeEqualsType (csenv:ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) (cxsln:(TraitConstraintInfo * TraitConstraintSln) option) ty1 ty2 = let ndeep = ndeep + 1 let aenv = csenv.EquivEnv let g = csenv.g @@ -1152,46 +1232,97 @@ and SolveTypeEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTr match sty1, sty2 with // type vars inside forall-types may be alpha-equivalent - | TType_var (tp1, _), TType_var (tp2, _) when typarEq tp1 tp2 || (match aenv.EquivTypars.TryFind tp1 with | Some tpTy1 when typeEquiv g tpTy1 ty2 -> true | _ -> false) -> - CompleteD - - // 'v1 = 'v2 - | TType_var (tp1, _), TType_var (tp2, _) when PreferUnifyTypar tp1 tp2 -> - SolveTyparEqualsType csenv ndeep m2 trace sty1 ty2 - - // 'v1 = 'v2 - | TType_var (tp1, _), TType_var (tp2, _) when not csenv.MatchingOnly && PreferUnifyTypar tp2 tp1 -> - SolveTyparEqualsType csenv ndeep m2 trace sty2 ty1 - - | TType_var (r, _), _ when not (IsRigid csenv r) -> - SolveTyparEqualsType csenv ndeep m2 trace sty1 ty2 - - | _, TType_var (r, _) when not csenv.MatchingOnly && not (IsRigid csenv r) -> - SolveTyparEqualsType csenv ndeep m2 trace sty2 ty1 + | TType_var (tp1, nullness1), TType_var (tp2, nullness2) when typarEq tp1 tp2 || (match aenv.EquivTypars.TryFind tp1 with | Some tpTy1 when typeEquiv g tpTy1 ty2 -> true | _ -> false) -> + SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullness2 + + | TType_var (tp1, nullness1), TType_var (tp2, nullness2) when PreferUnifyTypar tp1 tp2 -> + match nullness1.TryEvaluate(), nullness2.TryEvaluate() with + // Unifying 'T1? and 'T2? + | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithNull -> + SolveTyparEqualsType csenv ndeep m2 trace sty1 (TType_var (tp2, g.knownWithoutNull)) + //// Unifying 'T1 % and 'T2 % + //| ValueSome NullnessInfo.AmbivalentToNull, ValueSome NullnessInfo.AmbivalentToNull -> + // SolveTyparEqualsType csenv ndeep m2 trace sty1 (TType_var (tp2, g.knownWithoutNull)) + | _ -> + SolveTyparEqualsType csenv ndeep m2 trace sty1 ty2 ++ (fun () -> + let nullnessAfterSolution1 = combineNullness (nullnessOfTy g sty1) nullness1 + SolveNullnessEquiv csenv m2 trace ty1 ty2 nullnessAfterSolution1 nullness2 + ) + + | TType_var (tp1, nullness1), TType_var (tp2, nullness2) when not csenv.MatchingOnly && PreferUnifyTypar tp2 tp1 -> + match nullness1.TryEvaluate(), nullness2.TryEvaluate() with + // Unifying 'T1? and 'T2? + | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithNull -> + SolveTyparEqualsType csenv ndeep m2 trace sty2 (TType_var (tp1, g.knownWithoutNull)) + //// Unifying 'T1 % and 'T2 % + //| ValueSome NullnessInfo.AmbivalentToNull, ValueSome NullnessInfo.AmbivalentToNull -> + // SolveTyparEqualsType csenv ndeep m2 trace sty2 (TType_var (tp1, g.knownWithoutNull)) + | _ -> + // Unifying 'T1 ? and 'T2 % + // Unifying 'T1 % and 'T2 ? + SolveTyparEqualsType csenv ndeep m2 trace sty2 ty1 ++ (fun () -> + let nullnessAfterSolution2 = combineNullness (nullnessOfTy g sty2) nullness2 + SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullnessAfterSolution2 + ) + + | TType_var (tp1, nullness1), _ when not (IsRigid csenv tp1) -> + match nullness1.TryEvaluate(), (nullnessOfTy g sty2).TryEvaluate() with + // Unifying 'T1? and 'T2? + | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithNull -> + SolveTyparEqualsType csenv ndeep m2 trace sty1 (replaceNullnessOfTy g.knownWithoutNull sty2) + // Unifying 'T1 % and 'T2 % + //| ValueSome NullnessInfo.AmbivalentToNull, ValueSome NullnessInfo.AmbivalentToNull -> + // SolveTyparEqualsType csenv ndeep m2 trace sty1 (replaceNullnessOfTy g.knownWithoutNull sty2) + | _ -> + SolveTyparEqualsType csenv ndeep m2 trace sty1 ty2 ++ (fun () -> + let nullnessAfterSolution1 = combineNullness (nullnessOfTy g sty1) nullness1 + SolveNullnessEquiv csenv m2 trace ty1 ty2 nullnessAfterSolution1 (nullnessOfTy g sty2) + ) + + | _, TType_var (tp2, nullness2) when not csenv.MatchingOnly && not (IsRigid csenv tp2) -> + match (nullnessOfTy g sty1).TryEvaluate(), nullness2.TryEvaluate() with + // Unifying 'T1? and 'T2? + | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithNull -> + SolveTyparEqualsType csenv ndeep m2 trace sty2 (replaceNullnessOfTy g.knownWithoutNull sty1) + // Unifying 'T1 % and 'T2 % + //| ValueSome NullnessInfo.AmbivalentToNull, ValueSome NullnessInfo.AmbivalentToNull -> + // SolveTyparEqualsType csenv ndeep m2 trace sty2 (replaceNullnessOfTy g.knownWithoutNull sty1) + | _ -> + SolveTyparEqualsType csenv ndeep m2 trace sty2 ty1 ++ (fun () -> + let nullnessAfterSolution2 = combineNullness (nullnessOfTy g sty2) nullness2 + SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) nullnessAfterSolution2 + ) // Catch float<_>=float<1>, float32<_>=float32<1> and decimal<_>=decimal<1> - | _, TType_app (tc2, [ms], _) when (tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms])) -> - SolveTypeEqualsType csenv ndeep m2 trace None ms (TType_measure Measure.One) + | (_, TType_app (tc2, [ms2], nullness2)) when (tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms2])) -> + SolveTypeEqualsType csenv ndeep m2 trace None (TType_measure Measure.One) ms2 ++ (fun () -> + SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) nullness2 + ) - | TType_app (tc2, [ms], _), _ when (tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms])) -> - SolveTypeEqualsType csenv ndeep m2 trace None ms (TType_measure Measure.One) + | (TType_app (tc1, [ms1], nullness1), _) when (tc1.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc1 [ms1])) -> + SolveTypeEqualsType csenv ndeep m2 trace None ms1 (TType_measure Measure.One) ++ (fun () -> + SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 (nullnessOfTy g sty2) + ) - | TType_app (tc1, l1, _), TType_app (tc2, l2, _) when tyconRefEq g tc1 tc2 -> - SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2 + | TType_app (tc1, l1, nullness1), TType_app (tc2, l2, nullness2) when tyconRefEq g tc1 tc2 -> + SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2 ++ (fun () -> + SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullness2 + ) - | TType_app _, TType_app _ -> - localAbortD + | TType_app _, TType_app _ -> localAbortD | TType_tuple (tupInfo1, l1), TType_tuple (tupInfo2, l2) -> if evalTupInfoIsStruct tupInfo1 <> evalTupInfoIsStruct tupInfo2 then ErrorD (ConstraintSolverError(FSComp.SR.tcTupleStructMismatch(), csenv.m, m2)) else SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2 - | TType_anon (anonInfo1, l1),TType_anon (anonInfo2, l2) -> - SolveAnonInfoEqualsAnonInfo csenv m2 anonInfo1 anonInfo2 ++ (fun () -> + | TType_anon (anonInfo1, l1),TType_anon (anonInfo2, l2) -> + SolveAnonInfoEqualsAnonInfo csenv m2 anonInfo1 anonInfo2 ++ (fun () -> SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2) - | TType_fun (domainTy1, rangeTy1, _), TType_fun (domainTy2, rangeTy2, _) -> - SolveFunTypeEqn csenv ndeep m2 trace None domainTy1 domainTy2 rangeTy1 rangeTy2 + | TType_fun (domainTy1, rangeTy1, nullness1), TType_fun (domainTy2, rangeTy2, nullness2) -> + SolveFunTypeEqn csenv ndeep m2 trace None domainTy1 domainTy2 rangeTy1 rangeTy2 ++ (fun () -> + SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullness2 + ) | TType_measure ms1, TType_measure ms2 -> UnifyMeasures csenv trace ms1 ms2 @@ -1234,7 +1365,9 @@ and SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln origl1 origl2 = loop origl1 origl2 and SolveFunTypeEqn csenv ndeep m2 trace cxsln domainTy1 domainTy2 rangeTy1 rangeTy2 = trackErrors { - do! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln domainTy1 domainTy2 + // TODO NULLNESS: consider whether flipping the actual and expected in argument position + // causes other problems, e.g. better/worse diagnostics + do! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln domainTy2 domainTy1 return! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln rangeTy1 rangeTy2 } @@ -1257,41 +1390,56 @@ and SolveTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optional let denv = csenv.DisplayEnv match sty1, sty2 with - | TType_var (tp1, _), _ -> + | TType_var (tp1, nullness1) , _ -> match aenv.EquivTypars.TryFind tp1 with | Some tpTy1 -> SolveTypeSubsumesType csenv ndeep m2 trace cxsln tpTy1 ty2 | _ -> match sty2 with - | TType_var (r2, _) when typarEq tp1 r2 -> CompleteD - | TType_var (r, _) when not csenv.MatchingOnly -> SolveTyparSubtypeOfType csenv ndeep m2 trace r ty1 + | TType_var (r2, nullness2) when typarEq tp1 r2 -> + SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullness2 + | TType_var (r2, nullness2) when not csenv.MatchingOnly -> + SolveTyparSubtypeOfType csenv ndeep m2 trace r2 ty1 ++ (fun () -> + let nullnessAfterSolution2 = combineNullness (nullnessOfTy g sty2) nullness2 + SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 nullness1 nullnessAfterSolution2 + ) | _ -> SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ty1 ty2 - | _, TType_var (r, _) when not csenv.MatchingOnly -> - SolveTyparSubtypeOfType csenv ndeep m2 trace r ty1 + | _, TType_var (r2, nullness2) when not csenv.MatchingOnly -> + SolveTyparSubtypeOfType csenv ndeep m2 trace r2 ty1 ++ (fun () -> + let nullnessAfterSolution2 = combineNullness (nullnessOfTy g sty2) nullness2 + SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) nullnessAfterSolution2 + ) | TType_tuple (tupInfo1, l1), TType_tuple (tupInfo2, l2) -> if evalTupInfoIsStruct tupInfo1 <> evalTupInfoIsStruct tupInfo2 then ErrorD (ConstraintSolverError(FSComp.SR.tcTupleStructMismatch(), csenv.m, m2)) else SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2 (* nb. can unify since no variance *) + | TType_fun (domainTy1, rangeTy1, nullness1), TType_fun (domainTy2, rangeTy2, nullness2) -> + // nb. can unify since no variance + SolveFunTypeEqn csenv ndeep m2 trace cxsln domainTy1 domainTy2 rangeTy1 rangeTy2 ++ (fun () -> + SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 nullness1 nullness2 + ) + | TType_anon (anonInfo1, l1), TType_anon (anonInfo2, l2) -> SolveAnonInfoEqualsAnonInfo csenv m2 anonInfo1 anonInfo2 ++ (fun () -> SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2) (* nb. can unify since no variance *) - | TType_fun (domainTy1, rangeTy1, _), TType_fun (domainTy2, rangeTy2, _) -> - SolveFunTypeEqn csenv ndeep m2 trace cxsln domainTy1 domainTy2 rangeTy1 rangeTy2 (* nb. can unify since no variance *) - | TType_measure ms1, TType_measure ms2 -> UnifyMeasures csenv trace ms1 ms2 // Enforce the identities float=float<1>, float32=float32<1> and decimal=decimal<1> - | _, TType_app (tc2, [ms], _) when (tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms])) -> - SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms (TType_measure Measure.One) + | _, TType_app (tc2, [ms2], nullness2) when tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms2]) -> + SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms2 (TType_measure Measure.One) ++ (fun () -> + SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) nullness2 + ) - | TType_app (tc2, [ms], _), _ when (tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms])) -> - SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms (TType_measure Measure.One) + | TType_app (tc1, [ms1], nullness1), _ when tc1.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc1 [ms1]) -> + SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms1 (TType_measure Measure.One) ++ (fun () -> + SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 nullness1 (nullnessOfTy g sty2) + ) // Special subsumption rule for byref tags - | TType_app (tc1, l1, _), TType_app (tc2, l2, _) when tyconRefEq g tc1 tc2 && g.byref2_tcr.CanDeref && tyconRefEq g g.byref2_tcr tc1 -> + | TType_app (tc1, l1, _) , TType_app (tc2, l2, _) when tyconRefEq g tc1 tc2 && g.byref2_tcr.CanDeref && tyconRefEq g g.byref2_tcr tc1 -> match l1, l2 with | [ h1; tag1 ], [ h2; tag2 ] -> trackErrors { do! SolveTypeEqualsType csenv ndeep m2 trace None h1 h2 @@ -1303,8 +1451,10 @@ and SolveTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optional } | _ -> SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2 - | TType_app (tc1, l1, _), TType_app (tc2, l2, _) when tyconRefEq g tc1 tc2 -> - SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2 + | TType_app (tc1, l1, nullness1) , TType_app (tc2, l2, nullness2) when tyconRefEq g tc1 tc2 -> + SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2 ++ (fun () -> + SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 nullness1 nullness2 + ) | TType_ucase (uc1, l1), TType_ucase (uc2, l2) when g.unionCaseRefEq uc1 uc2 -> SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2 @@ -1901,7 +2051,7 @@ and MemberConstraintSolutionOfMethInfo css m minfo minst staticTyOpt = match callMethInfoOpt, callExpr with | Some methInfo, Expr.Op (TOp.ILCall (_, _, _, _, NormalValUse, _, _, ilMethRef, _, methInst, _), [], args, m) when (args, (objArgVars@allArgVars)) ||> List.lengthsEqAndForall2 (fun a b -> match a with Expr.Val (v, _, _) -> valEq v.Deref b | _ -> false) -> - let declaringTy = ImportProvidedType amap m (methInfo.PApply((fun x -> x.DeclaringType), m)) + let declaringTy = ImportProvidedType amap m (methInfo.PApply((fun x -> nonNull x.DeclaringType), m)) if isILAppTy g declaringTy then let extOpt = None // EXTENSION METHODS FROM TYPE PROVIDERS: for extension methods coming from the type providers we would have something here. ILMethSln(declaringTy, extOpt, ilMethRef, methInst, staticTyOpt) @@ -2160,15 +2310,26 @@ and EnforceConstraintConsistency (csenv: ConstraintSolverEnv) ndeep m2 trace ret do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argsTy1 argsTy2 return! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy1 retTy2 - | TyparConstraint.SupportsComparison _, TyparConstraint.IsDelegate _ - | TyparConstraint.IsDelegate _, TyparConstraint.SupportsComparison _ - | TyparConstraint.IsNonNullableStruct _, TyparConstraint.IsReferenceType _ + | TyparConstraint.SupportsComparison _, TyparConstraint.IsDelegate _ + | TyparConstraint.IsDelegate _ , TyparConstraint.SupportsComparison _ -> + return! ErrorD (Error(FSComp.SR.csDelegateComparisonConstraintInconsistent(), m)) + + | TyparConstraint.NotSupportsNull _, TyparConstraint.SupportsNull _ + | TyparConstraint.SupportsNull _, TyparConstraint.NotSupportsNull _ -> + return! ErrorD (Error(FSComp.SR.csNullNotNullConstraintInconsistent(), m)) + + | TyparConstraint.SupportsNull _, TyparConstraint.IsNonNullableStruct _ + | TyparConstraint.IsNonNullableStruct _, TyparConstraint.SupportsNull _ -> + return! ErrorD (Error(FSComp.SR.csStructNullConstraintInconsistent(), m)) + + | TyparConstraint.IsNonNullableStruct _, TyparConstraint.IsReferenceType _ | TyparConstraint.IsReferenceType _, TyparConstraint.IsNonNullableStruct _ -> return! ErrorD (Error(FSComp.SR.csStructConstraintInconsistent(), m)) | TyparConstraint.SupportsComparison _, TyparConstraint.SupportsComparison _ | TyparConstraint.SupportsEquality _, TyparConstraint.SupportsEquality _ | TyparConstraint.SupportsNull _, TyparConstraint.SupportsNull _ + | TyparConstraint.NotSupportsNull _, TyparConstraint.NotSupportsNull _ | TyparConstraint.IsNonNullableStruct _, TyparConstraint.IsNonNullableStruct _ | TyparConstraint.IsUnmanaged _, TyparConstraint.IsUnmanaged _ | TyparConstraint.IsReferenceType _, TyparConstraint.IsReferenceType _ @@ -2205,6 +2366,7 @@ and CheckConstraintImplication (csenv: ConstraintSolverEnv) tpc1 tpc2 = // comparison implies equality | TyparConstraint.SupportsComparison _, TyparConstraint.SupportsEquality _ | TyparConstraint.SupportsNull _, TyparConstraint.SupportsNull _ + | TyparConstraint.NotSupportsNull _, TyparConstraint.NotSupportsNull _ | TyparConstraint.IsNonNullableStruct _, TyparConstraint.IsNonNullableStruct _ | TyparConstraint.IsUnmanaged _, TyparConstraint.IsUnmanaged _ | TyparConstraint.IsReferenceType _, TyparConstraint.IsReferenceType _ @@ -2295,20 +2457,156 @@ and AddConstraint (csenv: ConstraintSolverEnv) ndeep m2 trace tp newConstraint () } -and SolveTypeUseSupportsNull (csenv: ConstraintSolverEnv) ndeep m2 trace ty = +and SolveNullnessSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) ty nullness = trackErrors { let g = csenv.g let m = csenv.m let denv = csenv.DisplayEnv - match tryDestTyparTy g ty with - | ValueSome destTypar -> - AddConstraint csenv ndeep m2 trace destTypar (TyparConstraint.SupportsNull m) - | ValueNone -> - if TypeSatisfiesNullConstraint g m ty then CompleteD else + match nullness with + | Nullness.Variable nv -> + if nv.IsSolved then + do! SolveNullnessSupportsNull csenv ndeep m2 trace ty nv.Solution + else + trace.Exec (fun () -> nv.Set KnownWithNull) (fun () -> nv.Unset()) + | Nullness.Known n1 -> + match n1 with + | NullnessInfo.AmbivalentToNull -> () + | NullnessInfo.WithNull -> () + | NullnessInfo.WithoutNull -> + if g.checkNullness then + if not (isObjTy g ty) then + return! WarnD(ConstraintSolverNullnessWarningWithType(denv, ty, n1, m, m2)) + } + +and SolveTypeSupportsNullCore (csenv:ConstraintSolverEnv) ndeep m2 trace ty = trackErrors { + let g = csenv.g + let m = csenv.m + let denv = csenv.DisplayEnv + if TypeNullIsExtraValueNew g m ty then + () + else match ty with | NullableTy g _ -> - ErrorD (ConstraintSolverError(FSComp.SR.csNullableTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2)) + return! ErrorD (ConstraintSolverError(FSComp.SR.csNullableTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2)) | _ -> - ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2)) + // If langFeatureNullness is on then solve, maybe give warnings + if g.langFeatureNullness then + let nullness = nullnessOfTy g ty + do! SolveNullnessSupportsNull csenv ndeep m2 trace ty nullness + + // If langFeatureNullness or checkNullness are off give the same errors as F# 4.5 + if not g.langFeatureNullness || not g.checkNullness then + if not (TypeNullIsExtraValue g m ty) then + return! ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2)) + } + +// This version prefers to constrain a type parameter definiton +and SolveTypeDefnSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 trace ty = + let g = csenv.g + let m = csenv.m + let denv = csenv.DisplayEnv + if g.langFeatureNullness then + match stripTyparEqns ty with + // If you set a type variable constrained with a T: null to U? then you don't induce an inference constraint + // of U: null. + // TODO: what about Obsolete? + | TType_var(_, nullness) when nullness.Evaluate() = NullnessInfo.WithNull -> CompleteD + | _ -> + match tryDestTyparTy g ty with + | ValueSome tp -> + AddConstraint csenv ndeep m2 trace tp (TyparConstraint.SupportsNull m) + | ValueNone -> + SolveTypeSupportsNullCore csenv ndeep m2 trace ty + else + match tryDestTyparTy g ty with + | ValueSome destTypar -> + AddConstraint csenv ndeep m2 trace destTypar (TyparConstraint.SupportsNull m) + | ValueNone -> + if TypeNullIsExtraValue g m ty then CompleteD else + match ty with + | NullableTy g _ -> + ErrorD (ConstraintSolverError(FSComp.SR.csNullableTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2)) + | _ -> + ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2)) + +// This version prefers to constrain the nullness annotation for a type annotation usage +and SolveTypeUseSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 trace ty = + let g = csenv.g + let m = csenv.m + let denv = csenv.DisplayEnv + if g.langFeatureNullness then + match stripTyparEqns ty with + | TType_var(tp, nullness) -> + AddConstraint csenv ndeep m2 trace tp (TyparConstraint.IsReferenceType m) ++ (fun () -> + SolveNullnessSupportsNull csenv ndeep m2 trace ty nullness) + | _ -> + SolveTypeSupportsNullCore csenv ndeep m2 trace ty + else + match tryDestTyparTy g ty with + | ValueSome destTypar -> + AddConstraint csenv ndeep m2 trace destTypar (TyparConstraint.SupportsNull m) + | ValueNone -> + if TypeNullIsExtraValue g m ty then CompleteD else + match ty with + | NullableTy g _ -> + ErrorD (ConstraintSolverError(FSComp.SR.csNullableTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2)) + | _ -> + ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2)) + +and SolveNullnessNotSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) ty nullness = trackErrors { + let g = csenv.g + let m = csenv.m + let denv = csenv.DisplayEnv + match nullness with + | Nullness.Variable nv -> + if nv.IsSolved then + do! SolveNullnessNotSupportsNull csenv ndeep m2 trace ty nv.Solution + else + trace.Exec (fun () -> nv.Set KnownWithoutNull) (fun () -> nv.Unset()) + | Nullness.Known n1 -> + match n1 with + | NullnessInfo.AmbivalentToNull -> () + | NullnessInfo.WithoutNull -> () + | NullnessInfo.WithNull -> + if g.checkNullness then + if not (isObjTy g ty) then + return! WarnD(ConstraintSolverNonNullnessWarningWithType(denv, ty, n1, m, m2)) + else + if TypeNullIsExtraValue g m ty then + return! ErrorD (ConstraintSolverError(FSComp.SR.csTypeHasNullAsExtraValue(NicePrint.minimalStringOfType denv ty), m, m2)) + } + +and SolveTypeNotSupportsNullCore (csenv:ConstraintSolverEnv) ndeep m2 trace ty = trackErrors { + let g = csenv.g + let m = csenv.m + let denv = csenv.DisplayEnv + if TypeNullIsTrueValue g ty then + // We can only give warnings here as F# 5.0 introduces these constraints into existing + // code via Option.ofObj and Option.toObj + do! WarnD (ConstraintSolverError(FSComp.SR.csTypeHasNullAsTrueValue(NicePrint.minimalStringOfType denv ty), m, m2)) + elif TypeNullIsExtraValueNew g m ty then + if g.checkNullness || TypeNullIsExtraValue g m ty then + do! WarnD (ConstraintSolverError(FSComp.SR.csTypeHasNullAsExtraValue(NicePrint.minimalStringOfType denv ty), m, m2)) + else + if g.checkNullness then + let nullness = nullnessOfTy g ty + do! SolveNullnessNotSupportsNull csenv ndeep m2 trace ty nullness + } + +// This version prefers to constrain a type parameter definiton +and SolveTypeDefnNotSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 trace ty = + let g = csenv.g + let m = csenv.m + //match stripTyparEqns ty with + //// If you set a type variable constrained with a T: __notnull to U then you don't induce an inference constraint + //// of U: __notnull. + //// TODO: what about Obsolete? + //| TType_var(_, nullness) when nullness.TryEvaluate() = Some NullnessInfo.WithoutNull || nullness.TryEvaluate() = Some NullnessInfo.AmbivalentToNull -> CompleteD + //| _ -> + match tryDestTyparTy g ty with + | ValueSome tp -> + AddConstraint csenv ndeep m2 trace tp (TyparConstraint.NotSupportsNull m) + | ValueNone -> + SolveTypeNotSupportsNullCore csenv ndeep m2 trace ty and SolveTypeSupportsComparison (csenv: ConstraintSolverEnv) ndeep m2 trace ty = let g = csenv.g @@ -2500,7 +2798,7 @@ and SolveTypeRequiresDefaultConstructor (csenv: ConstraintSolverEnv) ndeep m2 tr | ValueSome tp -> AddConstraint csenv ndeep m2 trace tp (TyparConstraint.RequiresDefaultConstructor m) | _ -> - if isStructTy g ty then + if isStructTy g ty && (isStructTupleTy g ty || isStructAnonRecdTy g ty || TypeHasDefaultValue g m ty) then if isStructTupleTy g ty then destStructTupleTy g ty |> IterateD (SolveTypeRequiresDefaultValue csenv ndeep m trace) elif isStructAnonRecdTy g ty then @@ -2603,7 +2901,9 @@ and CanMemberSigsMatchUpToCheck else return! ErrorD(Error (FSComp.SR.csMemberIsNotInstance(minfo.LogicalName), m)) else - return! MapCombineTDC2D subsumeTypes calledObjArgTys callerObjArgTys + // The object types must be non-null + let nonNullCalledObjArgTys = calledObjArgTys |> List.map (replaceNullnessOfTy g.knownWithoutNull) + return! MapCombineTDC2D subsumeTypes nonNullCalledObjArgTys callerObjArgTys } let! usesTDC3 = @@ -3544,6 +3844,20 @@ let AddCxMethodConstraint denv css m trace traitInfo = (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult +let AddCxTypeDefnSupportsNull denv css m trace ty = + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + PostponeOnFailedMemberConstraintResolution csenv trace + (fun csenv -> SolveTypeDefnSupportsNull csenv 0 m trace ty) + (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) + |> RaiseOperationResult + +let AddCxTypeDefnNotSupportsNull denv css m trace ty = + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + PostponeOnFailedMemberConstraintResolution csenv trace + (fun csenv -> SolveTypeDefnNotSupportsNull csenv 0 m trace ty) + (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) + |> RaiseOperationResult + let AddCxTypeUseSupportsNull denv css m trace ty = let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv PostponeOnFailedMemberConstraintResolution csenv trace diff --git a/src/Compiler/Checking/ConstraintSolver.fsi b/src/Compiler/Checking/ConstraintSolver.fsi index d6cc309c6b5..a0943c752bf 100644 --- a/src/Compiler/Checking/ConstraintSolver.fsi +++ b/src/Compiler/Checking/ConstraintSolver.fsi @@ -174,6 +174,26 @@ exception ConstraintSolverTypesNotInSubsumptionRelation of exception ConstraintSolverMissingConstraint of displayEnv: DisplayEnv * Typar * TyparConstraint * range * range +exception ConstraintSolverNullnessWarningEquivWithTypes of + DisplayEnv * + TType * + TType * + NullnessInfo * + NullnessInfo * + range * + range + +exception ConstraintSolverNullnessWarningWithTypes of + DisplayEnv * + TType * + TType * + NullnessInfo * + NullnessInfo * + range * + range + +exception ConstraintSolverNullnessWarningWithType of DisplayEnv * TType * NullnessInfo * range * range +exception ConstraintSolverNonNullnessWarningWithType of DisplayEnv * TType * NullnessInfo * range * range exception ConstraintSolverError of string * range * range exception ErrorFromApplyingDefault of @@ -296,6 +316,10 @@ val AddCxTypeMustSubsumeTypeMatchingOnlyUndoIfFailed: val AddCxMethodConstraint: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TraitConstraintInfo -> unit +val AddCxTypeDefnNotSupportsNull: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit + +val AddCxTypeDefnSupportsNull: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit + val AddCxTypeUseSupportsNull: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit val AddCxTypeMustSupportComparison: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit diff --git a/src/Compiler/Checking/InfoReader.fs b/src/Compiler/Checking/InfoReader.fs index 5a6b63722cc..769e38d3227 100644 --- a/src/Compiler/Checking/InfoReader.fs +++ b/src/Compiler/Checking/InfoReader.fs @@ -683,7 +683,7 @@ type InfoReader(g: TcGlobals, amap: Import.ImportMap) as this = // a decent hash function for these. canMemoize=(fun (_flags, _: range, ty) -> match stripTyEqns g ty with - | TType_app(tcref, [], _) -> tcref.TypeContents.tcaug_closed + | TType_app(tcref, [], _) -> tcref.TypeContents.tcaug_closed // TODO NULLNESS: consider whether ignoring _nullness is valid here | _ -> false), keyComparer= @@ -692,13 +692,13 @@ type InfoReader(g: TcGlobals, amap: Import.ImportMap) as this = // Ignoring the ranges - that's OK. flagsEq.Equals(flags1, flags2) && match stripTyEqns g ty1, stripTyEqns g ty2 with - | TType_app(tcref1, [], _), TType_app(tcref2, [], _) -> tyconRefEq g tcref1 tcref2 + | TType_app(tcref1, [], _),TType_app(tcref2, [], _) -> tyconRefEq g tcref1 tcref2 // TODO NULLNESS: consider whether ignoring _nullness is valid here | _ -> false member _.GetHashCode((flags, _, ty)) = // Ignoring the ranges - that's OK. flagsEq.GetHashCode flags + (match stripTyEqns g ty with - | TType_app(tcref, [], _) -> hash tcref.LogicalName + | TType_app(tcref, [], _) -> hash tcref.LogicalName // TODO NULLNESS: consider whether ignoring _nullness is valid here | _ -> 0) }) let FindImplicitConversionsUncached (ad, m, ty) = @@ -1071,7 +1071,7 @@ let TryFindMetadataInfoOfExternalEntityRef (infoReader: InfoReader) m eref = // Generalize to get a formal signature let formalTypars = eref.Typars m let formalTypeInst = generalizeTypars formalTypars - let ty = TType_app(eref, formalTypeInst, 0uy) + let ty = TType_app(eref, formalTypeInst, KnownAmbivalentToNull) if isILAppTy g ty then let formalTypeInfo = ILTypeInfo.FromType g ty Some(nlref.Ccu.FileName, formalTypars, formalTypeInfo) diff --git a/src/Compiler/Checking/MethodCalls.fs b/src/Compiler/Checking/MethodCalls.fs index ceb13545da8..e8d6850bc77 100644 --- a/src/Compiler/Checking/MethodCalls.fs +++ b/src/Compiler/Checking/MethodCalls.fs @@ -1183,8 +1183,14 @@ let BuildMethodCall tcVal g amap isMutable m isProp minfo valUseFlags minst objA // Build a 'call' to a struct default constructor | DefaultStructCtor (g, ty) -> - if not (TypeHasDefaultValue g m ty) then - errorR(Error(FSComp.SR.tcDefaultStructConstructorCall(), m)) + if g.langFeatureNullness then + if not (TypeHasDefaultValueNew g m ty) && not (TypeHasDefaultValue g m ty) then + errorR(Error(FSComp.SR.tcDefaultStructConstructorCall(), m)) + if g.checkNullness && not (TypeHasDefaultValueNew g m ty) then + warning(Error(FSComp.SR.tcDefaultStructConstructorCallNulls(), m)) + else + if not (TypeHasDefaultValue g m ty) then + errorR(Error(FSComp.SR.tcDefaultStructConstructorCall(), m)) mkDefault (m, ty), ty) let ILFieldStaticChecks g amap infoReader ad m (finfo : ILFieldInfo) = diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 6fa70c26fc7..0fde8caa167 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -1568,7 +1568,7 @@ let AddDeclaredTyparsToNameEnv check nenv typars = /// a fresh set of inference type variables for the type parameters. let FreshenTycon (ncenv: NameResolver) m (tcref: TyconRef) = let tinst = ncenv.InstantiationGenerator m (tcref.Typars m) - let improvedTy = ncenv.g.decompileType tcref tinst + let improvedTy = ncenv.g.decompileType tcref tinst ncenv.g.knownWithoutNull improvedTy /// Convert a reference to a named type into a type that includes @@ -1576,7 +1576,7 @@ let FreshenTycon (ncenv: NameResolver) m (tcref: TyconRef) = let FreshenTyconWithEnclosingTypeInst (ncenv: NameResolver) m (tinstEnclosing: TypeInst) (tcref: TyconRef) = let tps = ncenv.InstantiationGenerator m (tcref.Typars m) let tinst = List.skip tinstEnclosing.Length tps - let improvedTy = ncenv.g.decompileType tcref (tinstEnclosing @ tinst) + let improvedTy = ncenv.g.decompileType tcref (tinstEnclosing @ tinst) ncenv.g.knownWithoutNull improvedTy /// Convert a reference to a union case into a UnionCaseInfo that includes diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs index 2ab993e369a..21196099f96 100644 --- a/src/Compiler/Checking/NicePrint.fs +++ b/src/Compiler/Checking/NicePrint.fs @@ -769,6 +769,9 @@ module PrintTypes = | TyparConstraint.SupportsNull _ -> [wordL (tagKeyword "null") |> longConstraintPrefix] + | TyparConstraint.NotSupportsNull _ -> + [(wordL (tagKeyword "__notnull") (* ^^ wordL(tagKeyword "null") *) ) |> longConstraintPrefix] + | TyparConstraint.IsNonNullableStruct _ -> if denv.shortConstraints then [wordL (tagText "value type")] @@ -874,6 +877,12 @@ module PrintTypes = | [] -> tcL | [arg] -> layoutTypeWithInfoAndPrec denv env 2 arg ^^ tcL | args -> bracketIfL (prec <= 1) (bracketL (layoutTypesWithInfoAndPrec denv env 2 (sepL (tagPunctuation ",")) args) --- tcL) + + and layoutNullness part2 (nullness: Nullness) = + match nullness.Evaluate() with + | NullnessInfo.WithNull -> part2 ^^ wordL (tagText "__withnull") + | NullnessInfo.WithoutNull -> part2 + | NullnessInfo.AmbivalentToNull -> part2 ^^ wordL (tagText "__maybenull") // TODO NULLNESS: emit this optionally ^^ wordL (tagText "%") /// Layout a type, taking precedence into account to insert brackets where needed and layoutTypeWithInfoAndPrec denv env prec ty = @@ -934,8 +943,10 @@ module PrintTypes = bracketIfL (prec <= 4) funcTyL // Layout a type variable . - | TType_var (r, _) -> - layoutTyparRefWithInfo denv env r + | TType_var (r, nullness) -> + let part1 = layoutTyparRefWithInfo denv env r + let part2 = layoutNullness part1 nullness + part2 | TType_measure unt -> layoutMeasure denv unt @@ -2684,7 +2695,7 @@ let minimalStringsOfTwoTypes denv ty1 ty2 = let denv = denv.SetOpenPaths [] let denv = { denv with includeStaticParametersInTypeNames=true } let makeName t = - let assemblyName = PrintTypes.layoutAssemblyName denv t |> function | null | "" -> "" | name -> sprintf " (%s)" name + let assemblyName = PrintTypes.layoutAssemblyName denv t |> function "" -> "" | name -> sprintf " (%s)" name sprintf "%s%s" (stringOfTy denv t) assemblyName (makeName ty1, makeName ty2, stringOfTyparConstraints denv tpcs) diff --git a/src/Compiler/Checking/PostInferenceChecks.fs b/src/Compiler/Checking/PostInferenceChecks.fs index 145c7e0799c..cf855cd1ea7 100644 --- a/src/Compiler/Checking/PostInferenceChecks.fs +++ b/src/Compiler/Checking/PostInferenceChecks.fs @@ -428,6 +428,7 @@ and CheckTypeConstraintDeep cenv f g env x = | TyparConstraint.SupportsComparison _ | TyparConstraint.SupportsEquality _ | TyparConstraint.SupportsNull _ + | TyparConstraint.NotSupportsNull _ | TyparConstraint.IsNonNullableStruct _ | TyparConstraint.IsUnmanaged _ | TyparConstraint.IsReferenceType _ @@ -2532,13 +2533,34 @@ let CheckEntityDefn cenv env (tycon: Entity) = // Check fields. We check these late because we have to have first checked that the structs are // free of cycles - if tycon.IsStructOrEnumTycon then + if g.langFeatureNullness then for f in tycon.AllInstanceFieldsAsList do + let m = f.Range // Check if it's marked unsafe let zeroInitUnsafe = TryFindFSharpBoolAttribute g g.attrib_DefaultValueAttribute f.FieldAttribs if zeroInitUnsafe = Some true then - if not (TypeHasDefaultValue g m ty) then - errorR(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValue(), m)) + let ty = f.FormalType + if not (TypeHasDefaultValueNew g m ty) && not (TypeHasDefaultValue g m ty) then + if tycon.IsStructOrEnumTycon then + // Under F# 4.5 we gave a hard error for this case so we can give it now + errorR(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValue(), m)) + else + if g.checkNullness then + // Under F# 5.0 rules with checkNullness we can now give a warning for this case + warning(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValue(), m)) + + elif g.checkNullness && not (TypeHasDefaultValueNew g m ty) then + // Under F# 5.0 rules with checkNullness we can now give a warning for this case + warning(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValueNulls(), m)) + // These are the F# 4.5 rules, mistakenly only applied to structs + elif tycon.IsStructOrEnumTycon then + for f in tycon.AllInstanceFieldsAsList do + let m = f.Range + // Check if it's marked unsafe + let zeroInitUnsafe = TryFindFSharpBoolAttribute g g.attrib_DefaultValueAttribute f.FieldAttribs + if zeroInitUnsafe = Some true then + if not (TypeHasDefaultValue g m ty) then + errorR(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValue(), m)) // Check type abbreviations match tycon.TypeAbbrev with diff --git a/src/Compiler/Checking/SignatureConformance.fs b/src/Compiler/Checking/SignatureConformance.fs index 2aa8bf924db..921b6b0fc64 100644 --- a/src/Compiler/Checking/SignatureConformance.fs +++ b/src/Compiler/Checking/SignatureConformance.fs @@ -230,7 +230,7 @@ type Checker(g, amap, denv, remapInfo: SignatureRepackageInfo, checkingSig) = else let aNull2 = TypeNullIsExtraValue g m (generalizedTyconRef g (mkLocalTyconRef implTycon)) - let fNull2 = TypeNullIsExtraValue g m (generalizedTyconRef g (mkLocalTyconRef implTycon)) + let fNull2 = TypeNullIsExtraValue g m (generalizedTyconRef g (mkLocalTyconRef implTycon)) // TODO: should be sigTycon, raises extra errors if aNull2 && not fNull2 then errorR(Error(FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplementationSaysNull2(implTycon.TypeOrMeasureKind.ToString(), implTycon.DisplayName), m)) false diff --git a/src/Compiler/Checking/TypeHierarchy.fs b/src/Compiler/Checking/TypeHierarchy.fs index f6949c707d8..43302b24b46 100644 --- a/src/Compiler/Checking/TypeHierarchy.fs +++ b/src/Compiler/Checking/TypeHierarchy.fs @@ -46,7 +46,7 @@ let GetSuperTypeOfType g amap m ty = #if !NO_TYPEPROVIDERS | ProvidedTypeMetadata info -> let st = info.ProvidedType - let superOpt = st.PApplyOption((fun st -> match st.BaseType with null -> None | t -> Some t), m) + let superOpt = st.PApplyOption((fun st -> match st.BaseType with null -> None | t -> Some (nonNull t)), m) match superOpt with | None -> None | Some super -> Some(ImportProvidedType amap m super) @@ -81,7 +81,13 @@ let GetSuperTypeOfType g amap m ty = else None - resBeforeNull + match resBeforeNull with + | Some superTy -> + let nullness = nullnessOfTy g ty + let superTyWithNull = addNullnessToTy nullness superTy + Some superTyWithNull + | None -> + None /// Make a type for System.Collections.Generic.IList let mkSystemCollectionsGenericIListTy (g: TcGlobals) ty = @@ -264,6 +270,7 @@ let FoldHierarchyOfTypeAux followInterfaces allowMultiIntfInst skipUnref visitor | TyparConstraint.IsEnum _ | TyparConstraint.IsDelegate _ | TyparConstraint.SupportsNull _ + | TyparConstraint.NotSupportsNull _ | TyparConstraint.IsNonNullableStruct _ | TyparConstraint.IsUnmanaged _ | TyparConstraint.IsReferenceType _ @@ -395,6 +402,8 @@ let CopyTyparConstraints m tprefInst (tporig: Typar) = TyparConstraint.IsEnum (instType tprefInst underlyingTy, m) | TyparConstraint.SupportsComparison _ -> TyparConstraint.SupportsComparison m + | TyparConstraint.NotSupportsNull _ -> + TyparConstraint.NotSupportsNull m | TyparConstraint.SupportsEquality _ -> TyparConstraint.SupportsEquality m | TyparConstraint.IsDelegate(argTys, retTy, _) -> diff --git a/src/Compiler/Checking/TypeRelations.fs b/src/Compiler/Checking/TypeRelations.fs index 90d5bed1fcb..c12e6e7e8a4 100644 --- a/src/Compiler/Checking/TypeRelations.fs +++ b/src/Compiler/Checking/TypeRelations.fs @@ -156,7 +156,9 @@ let ChooseTyparSolutionAndRange (g: TcGlobals) amap (tp:Typar) = errorR(Error(FSComp.SR.typrelCannotResolveAmbiguityInPrintf(), m)) maxTy, m | TyparConstraint.SupportsNull m -> - maxTy, m + addNullnessToTy KnownWithNull maxTy, m + | TyparConstraint.NotSupportsNull m -> + maxTy, m // NOTE: this doesn't "force" non-nullness, since it is the default choice in 'obj' or 'int' | TyparConstraint.SupportsComparison m -> join m g.mk_IComparable_ty, m | TyparConstraint.SupportsEquality m -> diff --git a/src/Compiler/Checking/import.fs b/src/Compiler/Checking/import.fs index bf6c9e73006..a299ec893fe 100644 --- a/src/Compiler/Checking/import.fs +++ b/src/Compiler/Checking/import.fs @@ -163,8 +163,24 @@ let CanImportILTypeRef (env: ImportMap) m (tref: ILTypeRef) = /// /// Prefer the F# abbreviation for some built-in types, e.g. 'string' rather than /// 'System.String', since we prefer the F# abbreviation to the .NET equivalents. -let ImportTyconRefApp (env: ImportMap) tcref tyargs = - env.g.improveType tcref tyargs +let ImportTyconRefApp (env: ImportMap) tcref tyargs nullness = + env.g.improveType tcref tyargs nullness + +let ImportNullness (g: TcGlobals) = + ignore g + // if g.langFeatureNullness && g.assumeNullOnImport then + // KnownWithNull + // else + // TODO NULLNESS + KnownAmbivalentToNull + +let ImportNullnessForTyconRef (g: TcGlobals) (m: range) (tcref: TyconRef) = + ignore (g, tcref, m) + // if g.langFeatureNullness && g.assumeNullOnImport && TyconRefNullIsExtraValue g m tcref then + // KnownWithNull + // else + // TODO NULLNESS + KnownAmbivalentToNull /// Import an IL type as an F# type. let rec ImportILType (env: ImportMap) m tinst ty = @@ -175,12 +191,14 @@ let rec ImportILType (env: ImportMap) m tinst ty = | ILType.Array(bounds, ty) -> let n = bounds.Rank let elemTy = ImportILType env m tinst ty - mkArrayTy env.g n elemTy m + let nullness = ImportNullness env.g + mkArrayTy env.g n nullness elemTy m | ILType.Boxed tspec | ILType.Value tspec -> let tcref = ImportILTypeRef env m tspec.TypeRef let inst = tspec.GenericArgs |> List.map (ImportILType env m tinst) - ImportTyconRefApp env tcref inst + let nullness = ImportNullnessForTyconRef env.g m tcref + ImportTyconRefApp env tcref inst nullness | ILType.Byref ty -> mkByrefTy env.g (ImportILType env m tinst ty) @@ -192,6 +210,7 @@ let rec ImportILType (env: ImportMap) m tinst ty = | ILType.Modified(_, _, ty) -> // All custom modifiers are ignored + // NULLNESS TODO: pick up the optional attributes at this point and fold the array of nullness information into the conversion ImportILType env m tinst ty | ILType.TypeVar u16 -> @@ -200,7 +219,9 @@ let rec ImportILType (env: ImportMap) m tinst ty = List.item (int u16) tinst with _ -> error(Error(FSComp.SR.impNotEnoughTypeParamsInScopeWhileImporting(), m)) - ty + let nullness = ImportNullness env.g + let tyWithNullness = addNullnessToTy nullness ty + tyWithNullness /// Determines if an IL type can be imported as an F# type let rec CanImportILType (env: ImportMap) m ty = @@ -286,7 +307,8 @@ let rec ImportProvidedType (env: ImportMap) (m: range) (* (tinst: TypeInst) *) ( let g = env.g if st.PUntaint((fun st -> st.IsArray), m) then let elemTy = ImportProvidedType env m (* tinst *) (st.PApply((fun st -> st.GetElementType()), m)) - mkArrayTy g (st.PUntaint((fun st -> st.GetArrayRank()), m)) elemTy m + let nullness = ImportNullness env.g + mkArrayTy g (st.PUntaint((fun st -> st.GetArrayRank()), m)) nullness elemTy m elif st.PUntaint((fun st -> st.IsByRef), m) then let elemTy = ImportProvidedType env m (* tinst *) (st.PApply((fun st -> st.GetElementType()), m)) mkByrefTy g elemTy @@ -358,7 +380,9 @@ let rec ImportProvidedType (env: ImportMap) (m: range) (* (tinst: TypeInst) *) ( else genericArg) - ImportTyconRefApp env tcref genericArgs + let nullness = ImportNullnessForTyconRef env.g m tcref + + ImportTyconRefApp env tcref genericArgs nullness /// Import a provided method reference as an Abstract IL method reference let ImportProvidedMethodBaseAsILMethodRef (env: ImportMap) (m: range) (mbase: Tainted) = diff --git a/src/Compiler/Checking/infos.fs b/src/Compiler/Checking/infos.fs index 2fe6031aeae..e34858a4b73 100644 --- a/src/Compiler/Checking/infos.fs +++ b/src/Compiler/Checking/infos.fs @@ -395,7 +395,7 @@ let OptionalArgInfoOfProvidedParameter (amap: ImportMap) m (provParam : Tainted< let GetAndSanityCheckProviderMethod m (mi: Tainted<'T :> ProvidedMemberInfo>) (get : 'T -> ProvidedMethodInfo MaybeNull) err = match mi.PApply((fun mi -> (get mi :> ProvidedMethodBase MaybeNull)),m) with | Tainted.Null -> error(Error(err(mi.PUntaint((fun mi -> mi.Name),m),mi.PUntaint((fun mi -> (nonNull mi.DeclaringType).Name), m)), m)) // TODO NULLNESS: type isntantiation should not be needed - | meth -> meth + | Tainted.NonNull meth -> meth /// Try to get an arbitrary ProvidedMethodInfo associated with a property. let ArbitraryMethodInfoOfPropertyInfo (pi: Tainted) m = @@ -1262,7 +1262,7 @@ type MethInfo = // For non-generic type providers there is no difference let formalParams = [ [ for p in mi.PApplyArray((fun mi -> mi.GetParameters()), "GetParameters", m) do - let paramName = p.PUntaint((fun p -> match p.Name with null -> None | s -> Some s), m) + let paramName = p.PUntaint((fun p -> match p.Name with "" -> None | s -> Some s), m) let paramTy = ImportProvidedType amap m (p.PApply((fun p -> p.ParameterType), m)) let isIn, isOut, isOptional = p.PUntaint((fun p -> p.IsIn, p.IsOut, p.IsOptional), m) yield TSlotParam(paramName, paramTy, isIn, isOut, isOptional, []) ] ] @@ -1291,7 +1291,7 @@ type MethInfo = [ [for p in mi.PApplyArray((fun mi -> mi.GetParameters()), "GetParameters", m) do let paramName = match p.PUntaint((fun p -> p.Name), m) with - | null -> None + | "" -> None | name -> Some (mkSynId m name) let paramTy = match p.PApply((fun p -> p.ParameterType), m) with @@ -1509,7 +1509,7 @@ type RecdFieldInfo = member x.FieldType = actualTyOfRecdFieldRef x.RecdFieldRef x.TypeInst /// Get the enclosing (declaring) type of the field in an F#-declared record, class or struct type - member x.DeclaringType = TType_app (x.RecdFieldRef.TyconRef, x.TypeInst, 0uy) + member x.DeclaringType = TType_app (x.RecdFieldRef.TyconRef, x.TypeInst, KnownWithoutNull) // TODO NULLNESS - qualify this override x.ToString() = x.TyconRef.ToString() + "::" + x.LogicalName @@ -1938,7 +1938,7 @@ type PropInfo = #if !NO_TYPEPROVIDERS | ProvidedProp (_, pi, m) -> [ for p in pi.PApplyArray((fun pi -> pi.GetIndexParameters()), "GetIndexParameters", m) do - let paramName = p.PUntaint((fun p -> match p.Name with null -> None | s -> Some (mkSynId m s)), m) + let paramName = p.PUntaint((fun p -> match p.Name with "" -> None | s -> Some (mkSynId m s)), m) let paramTy = ImportProvidedType amap m (p.PApply((fun p -> p.ParameterType), m)) yield ParamNameAndType(paramName, paramTy) ] #endif diff --git a/src/Compiler/DependencyManager/DependencyProvider.fs b/src/Compiler/DependencyManager/DependencyProvider.fs index f80969b3880..b2ba19f5615 100644 --- a/src/Compiler/DependencyManager/DependencyProvider.fs +++ b/src/Compiler/DependencyManager/DependencyProvider.fs @@ -124,7 +124,9 @@ type IResolveDependenciesResult = /// #I @"c:\somepath\to\packages\1.1.1\ResolvedPackage" abstract Roots: seq +#if NO_CHECKNULLS [] +#endif type IDependencyManagerProvider = abstract Name: string abstract Key: string diff --git a/src/Compiler/DependencyManager/DependencyProvider.fsi b/src/Compiler/DependencyManager/DependencyProvider.fsi index a4c76e67b92..7618f353141 100644 --- a/src/Compiler/DependencyManager/DependencyProvider.fsi +++ b/src/Compiler/DependencyManager/DependencyProvider.fsi @@ -39,7 +39,9 @@ type IResolveDependenciesResult = abstract Roots: seq /// Wraps access to a DependencyManager implementation +#if NO_CHECKNULLS [] +#endif type IDependencyManagerProvider = /// Name of the dependency manager diff --git a/src/Compiler/Driver/CompilerConfig.fs b/src/Compiler/Driver/CompilerConfig.fs index 117aa66391c..687d776d090 100644 --- a/src/Compiler/Driver/CompilerConfig.fs +++ b/src/Compiler/Driver/CompilerConfig.fs @@ -194,11 +194,14 @@ type IRawFSharpAssemblyData = abstract TryGetILModuleDef: unit -> ILModuleDef option /// The raw F# signature data in the assembly, if any - abstract GetRawFSharpSignatureData: range * ilShortAssemName: string * fileName: string -> (string * (unit -> ReadOnlyByteMemory)) list + abstract GetRawFSharpSignatureData: + range * ilShortAssemName: string * fileName: string -> + (string * ((unit -> ReadOnlyByteMemory) * (unit -> ReadOnlyByteMemory) option)) list /// The raw F# optimization data in the assembly, if any abstract GetRawFSharpOptimizationData: - range * ilShortAssemName: string * fileName: string -> (string * (unit -> ReadOnlyByteMemory)) list + range * ilShortAssemName: string * fileName: string -> + (string * ((unit -> ReadOnlyByteMemory) * (unit -> ReadOnlyByteMemory) option)) list /// The table of type forwarders in the assembly abstract GetRawTypeForwarders: unit -> ILExportedTypesAndForwarders @@ -439,6 +442,7 @@ type TcConfigBuilder = mutable embedResources: string list mutable diagnosticsOptions: FSharpDiagnosticOptions mutable mlCompatibility: bool + mutable checkNullness: bool mutable checkOverflow: bool mutable showReferenceResolutions: bool mutable outputDir: string option @@ -673,6 +677,7 @@ type TcConfigBuilder = subsystemVersion = 4, 0 // per spec for 357994 useHighEntropyVA = false mlCompatibility = false + checkNullness = false checkOverflow = false showReferenceResolutions = false outputDir = None @@ -1246,6 +1251,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member _.embedResources = data.embedResources member _.diagnosticsOptions = data.diagnosticsOptions member _.mlCompatibility = data.mlCompatibility + member _.checkNullness = data.checkNullness member _.checkOverflow = data.checkOverflow member _.showReferenceResolutions = data.showReferenceResolutions member _.outputDir = data.outputDir diff --git a/src/Compiler/Driver/CompilerConfig.fsi b/src/Compiler/Driver/CompilerConfig.fsi index 7f29c346eb8..f97ba86d7d6 100644 --- a/src/Compiler/Driver/CompilerConfig.fsi +++ b/src/Compiler/Driver/CompilerConfig.fsi @@ -46,11 +46,13 @@ type IRawFSharpAssemblyData = /// Get the raw F# signature data in the assembly, if any abstract GetRawFSharpSignatureData: - m: range * ilShortAssemName: string * fileName: string -> (string * (unit -> ReadOnlyByteMemory)) list + m: range * ilShortAssemName: string * fileName: string -> + (string * ((unit -> ReadOnlyByteMemory) * (unit -> ReadOnlyByteMemory) option)) list /// Get the raw F# optimization data in the assembly, if any abstract GetRawFSharpOptimizationData: - m: range * ilShortAssemName: string * fileName: string -> (string * (unit -> ReadOnlyByteMemory)) list + m: range * ilShortAssemName: string * fileName: string -> + (string * ((unit -> ReadOnlyByteMemory) * (unit -> ReadOnlyByteMemory) option)) list /// Get the table of type forwarders in the assembly abstract GetRawTypeForwarders: unit -> ILExportedTypesAndForwarders @@ -286,6 +288,8 @@ type TcConfigBuilder = mutable mlCompatibility: bool + mutable checkNullness: bool + mutable checkOverflow: bool mutable showReferenceResolutions: bool @@ -620,6 +624,8 @@ type TcConfig = member mlCompatibility: bool + member checkNullness: bool + member checkOverflow: bool member showReferenceResolutions: bool diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index d0c83a20a5b..d3e03d95735 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -174,6 +174,10 @@ type Exception with | ConstraintSolverTupleDiffLengths (_, _, _, _, m, _) | ConstraintSolverInfiniteTypes (_, _, _, _, m, _) | ConstraintSolverMissingConstraint (_, _, _, m, _) + | ConstraintSolverNullnessWarningEquivWithTypes (_, _, _, _, _, m, _) + | ConstraintSolverNullnessWarningWithTypes (_, _, _, _, _, m, _) + | ConstraintSolverNullnessWarningWithType (_, _, _, m, _) + | ConstraintSolverNonNullnessWarningWithType (_, _, _, m, _) | ConstraintSolverTypesNotInEqualityRelation (_, _, _, m, _, _) | ConstraintSolverError (_, m, _) | ConstraintSolverTypesNotInSubsumptionRelation (_, _, _, m, _) @@ -339,6 +343,10 @@ type Exception with #endif | ErrorsFromAddingSubsumptionConstraint (_, _, _, _, _, ContextInfo.DowncastUsedInsteadOfUpcast _, _) -> fst (FSComp.SR.considerUpcast ("", "")) + | ConstraintSolverNullnessWarningEquivWithTypes _ -> 3261 + | ConstraintSolverNullnessWarningWithTypes _ -> 3262 + | ConstraintSolverNullnessWarningWithType _ -> 3263 + | ConstraintSolverNonNullnessWarningWithType _ -> 3264 | _ -> 193 type PhasedDiagnostic with @@ -442,6 +450,10 @@ module OldStyleMessages = let ConstraintSolverTupleDiffLengthsE () = Message("ConstraintSolverTupleDiffLengths", "%d%d") let ConstraintSolverInfiniteTypesE () = Message("ConstraintSolverInfiniteTypes", "%s%s") let ConstraintSolverMissingConstraintE () = Message("ConstraintSolverMissingConstraint", "%s") + let ConstraintSolverNullnessWarningEquivWithTypesE () = Message("ConstraintSolverNullnessWarningEquivWithTypes", "%s%s%s%s") + let ConstraintSolverNullnessWarningWithTypesE () = Message("ConstraintSolverNullnessWarningWithTypes", "%s%s%s%s") + let ConstraintSolverNullnessWarningWithTypeE () = Message("ConstraintSolverNullnessWarningWithType", "%s") + let ConstraintSolverNonNullnessWarningWithTypeE () = Message("ConstraintSolverNonNullnessWarningWithType", "%s") let ConstraintSolverTypesNotInEqualityRelation1E () = Message("ConstraintSolverTypesNotInEqualityRelation1", "%s%s") let ConstraintSolverTypesNotInEqualityRelation2E () = Message("ConstraintSolverTypesNotInEqualityRelation2", "%s%s") let ConstraintSolverTypesNotInSubsumptionRelationE () = Message("ConstraintSolverTypesNotInSubsumptionRelation", "%s%s%s") @@ -664,6 +676,42 @@ type Exception with if m.StartLine <> m2.StartLine then os.AppendString(SeeAlsoE().Format(stringOfRange m)) + | ConstraintSolverNullnessWarningEquivWithTypes (denv, ty1, ty2, nullness1, nullness2, m, m2) -> + + let t1, t2, _cxs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2 + + os.Append(ConstraintSolverNullnessWarningEquivWithTypesE().Format t1 t2 (nullness1.ToString()) (nullness2.ToString())) + |> ignore + + if m.StartLine <> m2.StartLine then + os.Append(SeeAlsoE().Format(stringOfRange m)) |> ignore + + | ConstraintSolverNullnessWarningWithTypes (denv, ty1, ty2, nullness1, nullness2, m, m2) -> + + let t1, t2, _cxs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2 + + os.Append(ConstraintSolverNullnessWarningWithTypesE().Format t1 t2 (nullness1.ToString()) (nullness2.ToString())) + |> ignore + + if m.StartLine <> m2.StartLine then + os.Append(SeeAlsoE().Format(stringOfRange m)) |> ignore + + | ConstraintSolverNullnessWarningWithType (denv, ty, _, m, m2) -> + + let t = NicePrint.minimalStringOfType denv ty + os.Append(ConstraintSolverNullnessWarningWithTypeE().Format(t)) |> ignore + + if m.StartLine <> m2.StartLine then + os.Append(SeeAlsoE().Format(stringOfRange m)) |> ignore + + | ConstraintSolverNonNullnessWarningWithType (denv, ty, _, m, m2) -> + + let t = NicePrint.minimalStringOfType denv ty + os.Append(ConstraintSolverNonNullnessWarningWithTypeE().Format(t)) |> ignore + + if m.StartLine <> m2.StartLine then + os.Append(SeeAlsoE().Format(stringOfRange m)) |> ignore + | ConstraintSolverMissingConstraint (denv, tpr, tpc, m, m2) -> os.AppendString( ConstraintSolverMissingConstraintE() @@ -816,7 +864,8 @@ type Exception with let argsMessage, returnType, genericParametersMessage = let retTy = - knownReturnType |> Option.defaultValue (TType_var(Typar.NewUnlinked(), 0uy)) + knownReturnType + |> Option.defaultValue (TType.TType_var(Typar.NewUnlinked(), KnownAmbivalentToNull)) let argRepr = callerArgs.ArgumentNamesAndTypes @@ -1220,9 +1269,10 @@ type Exception with | Parser.TOKEN_INTERP_STRING_BEGIN_PART -> SR.GetString("Parser.TOKEN.INTERP.STRING.BEGIN.PART") | Parser.TOKEN_INTERP_STRING_PART -> SR.GetString("Parser.TOKEN.INTERP.STRING.PART") | Parser.TOKEN_INTERP_STRING_END -> SR.GetString("Parser.TOKEN.INTERP.STRING.END") + | Parser.TOKEN_WITHNULL__ -> SR.GetString("Parser.TOKEN.WITHNULL__") + | Parser.TOKEN_NOTNULL__ -> SR.GetString("Parser.TOKEN.NOTNULL__") | unknown -> - Debug.Assert(false, "unknown token tag") - let result = sprintf "%+A" unknown + let result = sprintf "unknown token tag %+A" unknown Debug.Assert(false, result) result diff --git a/src/Compiler/Driver/CompilerImports.fs b/src/Compiler/Driver/CompilerImports.fs index d182a8d8ebf..61eb721aea4 100644 --- a/src/Compiler/Driver/CompilerImports.fs +++ b/src/Compiler/Driver/CompilerImports.fs @@ -58,11 +58,19 @@ let IsSignatureDataResource (r: ILResource) = || r.Name.StartsWithOrdinal FSharpSignatureCompressedDataResourceName || r.Name.StartsWithOrdinal FSharpSignatureDataResourceName2 +let IsSignatureDataResourceB (r: ILResource) = + r.Name.StartsWithOrdinal FSharpSignatureDataResourceNameB + || r.Name.StartsWithOrdinal FSharpSignatureCompressedDataResourceNameB + let IsOptimizationDataResource (r: ILResource) = r.Name.StartsWithOrdinal FSharpOptimizationDataResourceName || r.Name.StartsWithOrdinal FSharpOptimizationCompressedDataResourceName || r.Name.StartsWithOrdinal FSharpOptimizationDataResourceName2 +let IsOptimizationDataResourceB (r: ILResource) = + r.Name.StartsWithOrdinal FSharpOptimizationDataResourceNameB + || r.Name.StartsWithOrdinal FSharpOptimizationCompressedDataResourceNameB + let decompressResource (r: ILResource) = use raw = r.GetBytes().AsStream() use decompressed = new MemoryStream() @@ -71,71 +79,130 @@ let decompressResource (r: ILResource) = deflator.Close() ByteStorage.FromByteArray(decompressed.ToArray()).GetByteMemory() -let GetResourceNameAndSignatureDataFunc (r: ILResource) = - let resourceType, ccuName = - if r.Name.StartsWithOrdinal FSharpSignatureDataResourceName then - FSharpSignatureDataResourceName, String.dropPrefix r.Name FSharpSignatureDataResourceName - elif r.Name.StartsWithOrdinal FSharpSignatureCompressedDataResourceName then - FSharpSignatureCompressedDataResourceName, String.dropPrefix r.Name FSharpSignatureCompressedDataResourceName - elif r.Name.StartsWithOrdinal FSharpSignatureDataResourceName2 then - FSharpSignatureDataResourceName2, String.dropPrefix r.Name FSharpSignatureDataResourceName2 - else - failwith "GetSignatureDataResourceName" - - if resourceType = FSharpSignatureCompressedDataResourceName then - ccuName, (fun () -> decompressResource (r)) +let GetSignatureDataResourceName (r: ILResource) = + if r.Name.StartsWithOrdinal FSharpSignatureDataResourceName then + (fun () -> r.GetBytes()), String.dropPrefix r.Name FSharpSignatureDataResourceName + elif r.Name.StartsWithOrdinal FSharpSignatureCompressedDataResourceName then + (fun () -> decompressResource r), String.dropPrefix r.Name FSharpSignatureCompressedDataResourceName + elif r.Name.StartsWithOrdinal FSharpSignatureDataResourceNameB then + (fun () -> r.GetBytes()), String.dropPrefix r.Name FSharpSignatureDataResourceNameB + elif r.Name.StartsWithOrdinal FSharpSignatureCompressedDataResourceNameB then + (fun () -> decompressResource r), String.dropPrefix r.Name FSharpSignatureCompressedDataResourceNameB + elif r.Name.StartsWithOrdinal FSharpSignatureDataResourceName2 then + (fun () -> r.GetBytes()), String.dropPrefix r.Name FSharpSignatureDataResourceName2 else - ccuName, (fun () -> r.GetBytes()) - -let GetResourceNameAndOptimizationDataFunc (r: ILResource) = - let resourceType, ccuName = - if r.Name.StartsWithOrdinal FSharpOptimizationDataResourceName then - FSharpOptimizationDataResourceName, String.dropPrefix r.Name FSharpOptimizationDataResourceName - elif r.Name.StartsWithOrdinal FSharpOptimizationCompressedDataResourceName then - FSharpOptimizationCompressedDataResourceName, String.dropPrefix r.Name FSharpOptimizationCompressedDataResourceName - elif r.Name.StartsWithOrdinal FSharpOptimizationDataResourceName2 then - FSharpOptimizationDataResourceName2, String.dropPrefix r.Name FSharpOptimizationDataResourceName2 - else - failwith "GetOptimizationDataResourceName" - - if resourceType = FSharpOptimizationCompressedDataResourceName then - ccuName, (fun () -> decompressResource (r)) + failwith "unreachable" + +let GetResourceNameAndSignatureDataFuncs (resources: ILResource list) = + [ for r in resources do + if IsSignatureDataResource r then + let readerA, ccuName = GetSignatureDataResourceName r + + let readerB = + resources |> List.tryPick (fun rB -> + if IsSignatureDataResourceB rB then + let readerB, ccuNameB = GetSignatureDataResourceName rB + if ccuName = ccuNameB then + Some readerB + else None + else None) + + ccuName, (readerA, readerB) ] + +let GetOptimizationDataResourceName (r: ILResource) = + if r.Name.StartsWithOrdinal FSharpOptimizationDataResourceName then + (fun () -> r.GetBytes()), String.dropPrefix r.Name FSharpOptimizationDataResourceName + elif r.Name.StartsWithOrdinal FSharpOptimizationCompressedDataResourceName then + (fun () -> decompressResource r), String.dropPrefix r.Name FSharpOptimizationCompressedDataResourceName + elif r.Name.StartsWithOrdinal FSharpOptimizationDataResourceNameB then + (fun () -> r.GetBytes()), String.dropPrefix r.Name FSharpOptimizationDataResourceNameB + elif r.Name.StartsWithOrdinal FSharpOptimizationCompressedDataResourceNameB then + (fun () -> decompressResource r), String.dropPrefix r.Name FSharpOptimizationCompressedDataResourceNameB + elif r.Name.StartsWithOrdinal FSharpOptimizationDataResourceName2 then + (fun () -> r.GetBytes()), String.dropPrefix r.Name FSharpOptimizationDataResourceName2 else - ccuName, (fun () -> r.GetBytes()) + failwith $"GetOptimizationDataResourceName - {r.Name}" + +let GetResourceNameAndOptimizationDataFuncs (resources: ILResource list) = + [ for r in resources do + if IsOptimizationDataResource r then + let readerA, ccuName = GetOptimizationDataResourceName r + + let readerB = + resources |> List.tryPick (fun rB -> + if IsOptimizationDataResourceB rB then + let readerB, ccuNameB = GetOptimizationDataResourceName rB + if ccuName = ccuNameB then + Some readerB + else None + else None) + ccuName, (readerA, readerB) ] let IsReflectedDefinitionsResource (r: ILResource) = r.Name.StartsWithOrdinal(QuotationPickler.SerializedReflectedDefinitionsResourceNameBase) -let PickleToResource inMem file (g: TcGlobals) compress scope rName p x = +let ByteBufferToBytes compress (bytes: ByteBuffer) = + if compress then + let raw = new MemoryStream(bytes.AsMemory().ToArray()) + let compressed = new MemoryStream() + use deflator = new DeflateStream(compressed, CompressionLevel.Optimal) + raw.CopyTo deflator + deflator.Close() + compressed.ToArray() + else + bytes.AsMemory().ToArray() + +let PickleToResource inMem file (g: TcGlobals) compress scope rName rNameB p x = let file = PathMap.apply g.pathMap file - let bytes = - use bytes = pickleObjWithDanglingCcus inMem file g scope p x + let bytes, bytesB = pickleObjWithDanglingCcus inMem file g scope p x + use bytes = bytes + use bytesB = bytesB + let bytes = ByteBufferToBytes compress bytes + let bytesB = ByteBufferToBytes compress bytesB + let byteStorage = ByteStorage.FromByteArray(bytes) - if compress then - let raw = new MemoryStream(bytes.AsMemory().ToArray()) - let compressed = new MemoryStream() - use deflator = new DeflateStream(compressed, CompressionLevel.Optimal) - raw.CopyTo deflator - deflator.Close() - compressed.ToArray() + let byteStorageB = + if inMem then + ByteStorage.FromMemoryAndCopy(bytesB.AsMemory(), useBackingMemoryMappedFile = true) else - bytes.AsMemory().ToArray() + ByteStorage.FromByteArray(bytesB.AsMemory().ToArray()) - let byteStorage = ByteStorage.FromByteArray(bytes) + let resource = + { + Name = rName + Location = ILResourceLocation.Local(byteStorage) + Access = ILResourceAccess.Public + CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs + MetadataIndex = NoMetadataIdx + } - { - Name = rName - Location = ILResourceLocation.Local(byteStorage) - Access = ILResourceAccess.Public - CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs - MetadataIndex = NoMetadataIdx - } + let resourceB = + if bytesB.AsMemory().Length > 0 then + Some + { + Name = rNameB + Location = ILResourceLocation.Local(byteStorageB) + Access = ILResourceAccess.Public + CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs + MetadataIndex = NoMetadataIdx + } + else + None + + resource, resourceB -let GetSignatureData (file, ilScopeRef, ilModule, byteReader) : PickledDataWithReferences = - unpickleObjWithDanglingCcus file ilScopeRef ilModule unpickleCcuInfo (byteReader ()) +let GetSignatureData (file, ilScopeRef, ilModule, byteReaderA, byteReaderB) : PickledDataWithReferences = + let memA = byteReaderA () -let WriteSignatureData (tcConfig: TcConfig, tcGlobals, exportRemapping, ccu: CcuThunk, fileName, inMem) : ILResource = + let memB = + (match byteReaderB with + | None -> ByteMemory.Empty.AsReadOnly() + | Some br -> br ()) + + unpickleObjWithDanglingCcus file ilScopeRef ilModule unpickleCcuInfo memA memB + +let WriteSignatureData (tcConfig: TcConfig, tcGlobals, exportRemapping, ccu: CcuThunk, fileName, inMem) = let mspec = ApplyExportRemappingToEntity tcGlobals exportRemapping ccu.Contents if tcConfig.dumpSignatureData then @@ -150,13 +217,19 @@ let WriteSignatureData (tcConfig: TcConfig, tcGlobals, exportRemapping, ccu: Ccu // For historical reasons, we use a different resource name for FSharp.Core, so older F# compilers // don't complain when they see the resource. - let rName, compress = + let rName = if tcConfig.compressMetadata then - FSharpSignatureCompressedDataResourceName, true + FSharpSignatureCompressedDataResourceName elif ccu.AssemblyName = getFSharpCoreLibraryName then - FSharpSignatureDataResourceName2, false + FSharpSignatureDataResourceName2 + else + FSharpSignatureDataResourceName + + let rNameB = + if tcConfig.compressMetadata then + FSharpSignatureCompressedDataResourceNameB else - FSharpSignatureDataResourceName, false + FSharpSignatureDataResourceNameB let includeDir = if String.IsNullOrEmpty tcConfig.implicitIncludeDir then @@ -170,9 +243,10 @@ let WriteSignatureData (tcConfig: TcConfig, tcGlobals, exportRemapping, ccu: Ccu inMem fileName tcGlobals - compress + tcConfig.compressMetadata ccu (rName + ccu.AssemblyName) + (rNameB + ccu.AssemblyName) pickleCcuInfo { mspec = mspec @@ -180,28 +254,56 @@ let WriteSignatureData (tcConfig: TcConfig, tcGlobals, exportRemapping, ccu: Ccu usesQuotations = ccu.UsesFSharp20PlusQuotations } -let GetOptimizationData (file, ilScopeRef, ilModule, byteReader) = - unpickleObjWithDanglingCcus file ilScopeRef ilModule Optimizer.u_CcuOptimizationInfo (byteReader ()) +let GetOptimizationData (file, ilScopeRef, ilModule, byteReaderA, byteReaderB) = + let memA = byteReaderA () + + let memB = + (match byteReaderB with + | None -> ByteMemory.Empty.AsReadOnly() + | Some br -> br ()) + + unpickleObjWithDanglingCcus file ilScopeRef ilModule Optimizer.u_CcuOptimizationInfo memA memB let WriteOptimizationData (tcConfig: TcConfig, tcGlobals, fileName, inMem, ccu: CcuThunk, modulInfo) = // For historical reasons, we use a different resource name for FSharp.Core, so older F# compilers // don't complain when they see the resource. - let rName, compress = + let rName = if tcConfig.compressMetadata then - FSharpOptimizationCompressedDataResourceName, true + FSharpOptimizationCompressedDataResourceName elif ccu.AssemblyName = getFSharpCoreLibraryName then - FSharpOptimizationDataResourceName2, false + FSharpOptimizationDataResourceName2 + else + FSharpOptimizationDataResourceName + + let rNameB = + if tcConfig.compressMetadata then + FSharpOptimizationCompressedDataResourceNameB else - FSharpOptimizationDataResourceName, false + FSharpOptimizationDataResourceNameB - PickleToResource inMem fileName tcGlobals compress ccu (rName + ccu.AssemblyName) Optimizer.p_CcuOptimizationInfo modulInfo + PickleToResource + inMem + fileName + tcGlobals + tcConfig.compressMetadata + ccu + (rName + ccu.AssemblyName) + (rNameB + ccu.AssemblyName) + Optimizer.p_CcuOptimizationInfo + modulInfo let EncodeSignatureData (tcConfig: TcConfig, tcGlobals, exportRemapping, generatedCcu, outfile, isIncrementalBuild) = if tcConfig.GenerateSignatureData then - let resource = + let resource1, resource2 = WriteSignatureData(tcConfig, tcGlobals, exportRemapping, generatedCcu, outfile, isIncrementalBuild) - let resources = [ resource ] + let resources = + [ + resource1 + match resource2 with + | None -> () + | Some r -> r + ] let sigAttr = mkSignatureDataVersionAttr tcGlobals (parseILVersion FSharpBinaryMetadataFormatRevision) @@ -220,9 +322,18 @@ let EncodeOptimizationData (tcGlobals, tcConfig: TcConfig, outfile, exportRemapp else data - [ + let r1, r2 = WriteOptimizationData(tcConfig, tcGlobals, outfile, isIncrementalBuild, ccu, optData) - ] + + let resources = + [ + r1 + match r2 with + | None -> () + | Some r -> r + ] + + resources else [] @@ -854,12 +965,7 @@ type RawFSharpAssemblyDataBackedByFileOnDisk(ilModule: ILModuleDef, ilAssemblyRe member _.GetRawFSharpSignatureData(m, ilShortAssemName, fileName) = let resources = ilModule.Resources.AsList() - let sigDataReaders = - [ - for r in resources do - if IsSignatureDataResource r then - GetResourceNameAndSignatureDataFunc r - ] + let sigDataReaders = GetResourceNameAndSignatureDataFuncs resources let sigDataReaders = if sigDataReaders.IsEmpty && List.contains ilShortAssemName externalSigAndOptData then @@ -868,27 +974,22 @@ type RawFSharpAssemblyDataBackedByFileOnDisk(ilModule: ILModuleDef, ilAssemblyRe if not (FileSystem.FileExistsShim sigFileName) then error (Error(FSComp.SR.buildExpectedSigdataFile (FileSystem.GetFullPathShim sigFileName), m)) - [ - (ilShortAssemName, - fun () -> - FileSystem - .OpenFileForReadShim(sigFileName, useMemoryMappedFile = true, shouldShadowCopy = true) - .AsByteMemory() - .AsReadOnly()) - ] + let readerA () = + FileSystem + .OpenFileForReadShim(sigFileName, useMemoryMappedFile = true, shouldShadowCopy = true) + .AsByteMemory() + .AsReadOnly() + + [ (ilShortAssemName, (readerA, None)) ] else sigDataReaders sigDataReaders member _.GetRawFSharpOptimizationData(m, ilShortAssemName, fileName) = - let optDataReaders = - ilModule.Resources.AsList() - |> List.choose (fun r -> - if IsOptimizationDataResource r then - Some(GetResourceNameAndOptimizationDataFunc r) - else - None) + let resources = ilModule.Resources.AsList() + + let optDataReaders = GetResourceNameAndOptimizationDataFuncs resources // Look for optimization data in a file let optDataReaders = @@ -896,17 +997,17 @@ type RawFSharpAssemblyDataBackedByFileOnDisk(ilModule: ILModuleDef, ilAssemblyRe let optDataFile = Path.ChangeExtension(fileName, "optdata") if not (FileSystem.FileExistsShim optDataFile) then - let fullPath = FileSystem.GetFullPathShim optDataFile - error (Error(FSComp.SR.buildExpectedFileAlongSideFSharpCore (optDataFile, fullPath), m)) - - [ - (ilShortAssemName, - (fun () -> - FileSystem - .OpenFileForReadShim(optDataFile, useMemoryMappedFile = true, shouldShadowCopy = true) - .AsByteMemory() - .AsReadOnly())) - ] + error ( + Error(FSComp.SR.buildExpectedFileAlongSideFSharpCore (optDataFile, FileSystem.GetFullPathShim optDataFile), m) + ) + + let readerA () = + FileSystem + .OpenFileForReadShim(optDataFile, useMemoryMappedFile = true, shouldShadowCopy = true) + .AsByteMemory() + .AsReadOnly() + + [ (ilShortAssemName, (readerA, None)) ] else optDataReaders @@ -945,20 +1046,11 @@ type RawFSharpAssemblyData(ilModule: ILModuleDef, ilAssemblyRefs) = member _.GetRawFSharpSignatureData(_, _, _) = let resources = ilModule.Resources.AsList() - - [ - for r in resources do - if IsSignatureDataResource r then - GetResourceNameAndSignatureDataFunc r - ] + GetResourceNameAndSignatureDataFuncs resources member _.GetRawFSharpOptimizationData(_, _, _) = - ilModule.Resources.AsList() - |> List.choose (fun r -> - if IsOptimizationDataResource r then - Some(GetResourceNameAndOptimizationDataFunc r) - else - None) + let resources = ilModule.Resources.AsList() + GetResourceNameAndOptimizationDataFuncs resources member _.GetRawTypeForwarders() = match ilModule.Manifest with @@ -2001,9 +2093,9 @@ and [] TcImports let ccuRawDataAndInfos = ilModule.GetRawFSharpSignatureData(m, ilShortAssemName, fileName) - |> List.map (fun (ccuName, sigDataReader) -> + |> List.map (fun (ccuName, (sigDataReader, sigDataReaderB)) -> let data = - GetSignatureData(fileName, ilScopeRef, ilModule.TryGetILModuleDef(), sigDataReader) + GetSignatureData(fileName, ilScopeRef, ilModule.TryGetILModuleDef(), sigDataReader, sigDataReaderB) let optDatas = Map.ofList optDataReaders @@ -2051,9 +2143,9 @@ and [] TcImports lazy (match Map.tryFind ccuName optDatas with | None -> None - | Some info -> + | Some (readerA, readerB) -> let data = - GetOptimizationData(fileName, ilScopeRef, ilModule.TryGetILModuleDef(), info) + GetOptimizationData(fileName, ilScopeRef, ilModule.TryGetILModuleDef(), readerA, readerB) let fixupThunk () = data.OptionalFixup(fun nm -> availableToOptionalCcu (tcImports.FindCcu(ctok, m, nm, lookupOnly = false))) @@ -2494,6 +2586,7 @@ and [] TcImports tcConfig.implicitIncludeDir, tcConfig.mlCompatibility, tcConfig.isInteractive, + tcConfig.checkNullness, tcConfig.useReflectionFreeCodeGen, tryFindSysTypeCcu, tcConfig.emitDebugInfoInQuotations, diff --git a/src/Compiler/Driver/CompilerImports.fsi b/src/Compiler/Driver/CompilerImports.fsi index f9fa17487ae..70f551c0f49 100644 --- a/src/Compiler/Driver/CompilerImports.fsi +++ b/src/Compiler/Driver/CompilerImports.fsi @@ -37,13 +37,20 @@ exception MSBuildReferenceResolutionError of message: string * warningCode: stri /// Determine if an IL resource attached to an F# assembly is an F# signature data resource val IsSignatureDataResource: ILResource -> bool +/// Determine if an IL resource attached to an F# assembly is an F# signature data resource (data stream B) +val IsSignatureDataResourceB: ILResource -> bool + /// Determine if an IL resource attached to an F# assembly is an F# optimization data resource val IsOptimizationDataResource: ILResource -> bool +/// Determine if an IL resource attached to an F# assembly is an F# optimization data resource (data sream B) +val IsOptimizationDataResourceB: ILResource -> bool + /// Determine if an IL resource attached to an F# assembly is an F# quotation data resource for reflected definitions val IsReflectedDefinitionsResource: ILResource -> bool -val GetResourceNameAndSignatureDataFunc: ILResource -> string * (unit -> ReadOnlyByteMemory) +val GetResourceNameAndSignatureDataFuncs: + ILResource list -> (string * ((unit -> ReadOnlyByteMemory) * (unit -> ReadOnlyByteMemory) option)) list /// Encode the F# interface data into a set of IL attributes and resources val EncodeSignatureData: diff --git a/src/Compiler/Driver/CompilerOptions.fs b/src/Compiler/Driver/CompilerOptions.fs index 9592a660491..501a45b595f 100644 --- a/src/Compiler/Driver/CompilerOptions.fs +++ b/src/Compiler/Driver/CompilerOptions.fs @@ -859,6 +859,14 @@ let errorsAndWarningsFlags (tcConfigB: TcConfigBuilder) = Some(FSComp.SR.optsWarnOn ()) ) + CompilerOption( + "checknulls", + tagNone, + OptionSwitch(fun switch -> tcConfigB.checkNullness <- switch = OptionSwitch.On), + None, + Some(FSComp.SR.optsCheckNulls ()) + ) + CompilerOption( "consolecolors", tagNone, diff --git a/src/Compiler/Driver/GraphChecking/FileContentMapping.fs b/src/Compiler/Driver/GraphChecking/FileContentMapping.fs index b0b44e941fb..b42310bb6a1 100644 --- a/src/Compiler/Driver/GraphChecking/FileContentMapping.fs +++ b/src/Compiler/Driver/GraphChecking/FileContentMapping.fs @@ -240,6 +240,7 @@ let visitSynType (t: SynType) : FileContentEntry list = let continuations = List.map (snd >> visit) fields Continuation.concatenate continuations continuation | SynType.Array (elementType = elementType) -> visit elementType continuation + | SynType.WithNull (innerType = innerType) -> visit innerType continuation | SynType.Fun (argType, returnType, _, _) -> let continuations = List.map visit [ argType; returnType ] Continuation.concatenate continuations continuation @@ -250,6 +251,7 @@ let visitSynType (t: SynType) : FileContentEntry list = | SynType.HashConstraint (innerType, _) -> visit innerType continuation | SynType.MeasurePower (baseMeasure = baseMeasure) -> visit baseMeasure continuation | SynType.StaticConstant _ -> continuation [] + | SynType.StaticConstantNull _ -> continuation [] | SynType.StaticConstantExpr (expr, _) -> continuation (visitSynExpr expr) | SynType.StaticConstantNamed (ident, value, _) -> let continuations = List.map visit [ ident; value ] @@ -287,6 +289,7 @@ let visitSynTypeConstraint (tc: SynTypeConstraint) : FileContentEntry list = | SynTypeConstraint.WhereTyparIsReferenceType _ | SynTypeConstraint.WhereTyparIsUnmanaged _ | SynTypeConstraint.WhereTyparSupportsNull _ + | SynTypeConstraint.WhereTyparNotSupportsNull _ | SynTypeConstraint.WhereTyparIsComparable _ | SynTypeConstraint.WhereTyparIsEquatable _ -> () | SynTypeConstraint.WhereTyparDefaultsToType (typeName = typeName) -> yield! visitSynType typeName diff --git a/src/Compiler/Driver/StaticLinking.fs b/src/Compiler/Driver/StaticLinking.fs index 54a47568f40..361c48b5cf1 100644 --- a/src/Compiler/Driver/StaticLinking.fs +++ b/src/Compiler/Driver/StaticLinking.fs @@ -184,7 +184,8 @@ let StaticLinkILModules // Save only the interface/optimization attributes of generated data let intfDataResources, others = - allResources |> List.partition (snd >> IsSignatureDataResource) + allResources + |> List.partition (fun (_, r) -> IsSignatureDataResource r || IsSignatureDataResourceB r) let intfDataResources = [ @@ -194,7 +195,8 @@ let StaticLinkILModules ] let optDataResources, others = - others |> List.partition (snd >> IsOptimizationDataResource) + others + |> List.partition (fun (_, r) -> IsOptimizationDataResource r || IsOptimizationDataResourceB r) let optDataResources = [ diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 0da140f884d..fce80a8d230 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1514,6 +1514,19 @@ notAFunctionButMaybeDeclaration,"This value is not a function and cannot be appl 3250,expressionHasNoName,"Expression does not have a name." 3251,chkNoFirstClassNameOf,"Using the 'nameof' operator as a first-class function value is not permitted." 3252,tcIllegalByrefsInOpenTypeDeclaration,"Byref types are not allowed in an open type declaration." +3260,tcTypeDoesNotHaveAnyNull,"The type '%s' does not support a nullness qualitification." +#3261 reserved for ConstraintSolverNullnessWarningEquivWithTypes +#3262 reserved for ConstraintSolverNullnessWarningWithTypes +#3263 reserved for ConstraintSolverNullnessWarningWithType +#3264 reserved for ConstraintSolverNonNullnessWarningWithType +3266,tcDefaultStructConstructorCallNulls,"Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable." +3267,chkValueWithDefaultValueMustHaveDefaultValueNulls,"Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable." +3268,csNullNotNullConstraintInconsistent,"The constraints 'null' and 'not null' are inconsistent" +3269,csStructNullConstraintInconsistent,"The constraints 'struct' and 'null' are inconsistent" +3270,csDelegateComparisonConstraintInconsistent,"The constraints 'delegate' and 'comparison' are inconsistent" +3271,tcNullnessCheckingNotEnabled,"The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored." +csTypeHasNullAsTrueValue,"The type '%s' has 'null' as a true representation value but a constraint does not permit this" +csTypeHasNullAsExtraValue,"The type '%s' has 'null' as an extra value but a constraint does not permit this" 3300,chkInvalidFunctionParameterType,"The parameter '%s' has an invalid type '%s'. This is not permitted by the rules of Common IL." 3301,chkInvalidFunctionReturnType,"The function or method has an invalid return type '%s'. This is not permitted by the rules of Common IL." 3302,packageManagementRequiresVFive,"The 'package management' feature requires language version 5.0 or above" @@ -1528,6 +1541,8 @@ notAFunctionButMaybeDeclaration,"This value is not a function and cannot be appl 3353,chkFeatureNotSupportedInLibrary,"Feature '%s' requires the F# library for language version %s or greater." 3360,parsEqualsMissingInTypeDefinition,"Unexpected token in type definition. Expected '=' after the type '%s'." useSdkRefs,"Use reference assemblies for .NET framework references when available (Enabled by default)." +optsCheckNulls,"Enable nullness declarations and checks" +fSharpBannerVersion,"%s for F# %s" optsGetLangVersions,"Display the allowed values for language version." optsSetLangVersion,"Specify language version such as 'latest' or 'preview'." optsSupportedLangVersions,"Supported language versions:" @@ -1545,6 +1560,7 @@ featurePackageManagement,"package management" featureFromEndSlicing,"from-end slicing" featureFixedIndexSlice3d4d,"fixed-index slice 3d/4d" featureAndBang,"applicative computation expressions" +featureNullnessChecking,"nullness checking" featureResumableStateMachines,"resumable state machines" featureNullableOptionalInterop,"nullable optional interop" featureDefaultInterfaceMemberConsumption,"default interface member consumption" diff --git a/src/Compiler/FSStrings.resx b/src/Compiler/FSStrings.resx index 92013c7bba2..417b7b77fe0 100644 --- a/src/Compiler/FSStrings.resx +++ b/src/Compiler/FSStrings.resx @@ -129,6 +129,18 @@ A type parameter is missing a constraint '{0}' + + Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'. + + + Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'. + + + Nullness warning: The type '{0}' does not support nullness. + + + Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null. + The unit of measure '{0}' does not match the unit of measure '{1}' @@ -441,6 +453,12 @@ keyword 'fixed' + + keyword '__withnull' + + + keyword '__notnull' + interpolated string diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj index 54f68ef21d1..632cab7f8bc 100644 --- a/src/Compiler/FSharp.Compiler.Service.fsproj +++ b/src/Compiler/FSharp.Compiler.Service.fsproj @@ -1,4 +1,4 @@ - + @@ -13,6 +13,7 @@ FSharp.Compiler.Service true $(DefineConstants);COMPILER + true $(DefineConstants);FSHARPCORE_USE_PACKAGE $(OtherFlags) --extraoptimizationloops:1 diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index f46b0dbeee1..cf5a3680b7c 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -37,6 +37,7 @@ type LanguageFeature = | StringInterpolation | OverloadsForCustomOperations | ExpandedMeasurables + | NullnessChecking | StructActivePattern | PrintfBinaryFormat | IndexerNotationWithoutDot @@ -144,6 +145,7 @@ type LanguageVersion(versionText) = // F# preview LanguageFeature.FromEndSlicing, previewVersion + LanguageFeature.NullnessChecking, previewVersion LanguageFeature.MatchNotAllowedForUnionCaseWithNoData, previewVersion LanguageFeature.CSharpExtensionAttributeNotRequired, previewVersion LanguageFeature.ErrorForNonVirtualMembersOverrides, previewVersion @@ -238,6 +240,7 @@ type LanguageVersion(versionText) = | LanguageFeature.FromEndSlicing -> FSComp.SR.featureFromEndSlicing () | LanguageFeature.FixedIndexSlice3d4d -> FSComp.SR.featureFixedIndexSlice3d4d () | LanguageFeature.AndBang -> FSComp.SR.featureAndBang () + | LanguageFeature.NullnessChecking -> FSComp.SR.featureNullnessChecking () | LanguageFeature.ResumableStateMachines -> FSComp.SR.featureResumableStateMachines () | LanguageFeature.NullableOptionalInterop -> FSComp.SR.featureNullableOptionalInterop () | LanguageFeature.DefaultInterfaceMemberConsumption -> FSComp.SR.featureDefaultInterfaceMemberConsumption () diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi index d12c77fdcbe..22abb8e4bbb 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fsi +++ b/src/Compiler/Facilities/LanguageFeatures.fsi @@ -27,6 +27,7 @@ type LanguageFeature = | StringInterpolation | OverloadsForCustomOperations | ExpandedMeasurables + | NullnessChecking | StructActivePattern | PrintfBinaryFormat | IndexerNotationWithoutDot diff --git a/src/Compiler/Interactive/fsi.fs b/src/Compiler/Interactive/fsi.fs index 1c7e7bcd2ac..97c3cc08d84 100644 --- a/src/Compiler/Interactive/fsi.fs +++ b/src/Compiler/Interactive/fsi.fs @@ -1570,7 +1570,7 @@ let rec ConvReflectionTypeToILType (reflectionTy: Type) = if ctors.Length = 1 - && ctors[ 0 ].GetCustomAttribute() <> null + && not (isNull (box (ctors[ 0 ].GetCustomAttribute()))) && not ctors[0].IsPublic && IsCompilerGeneratedName reflectionTy.Name then @@ -3283,7 +3283,7 @@ type internal MagicAssemblyResolution() = fsiDynamicCompiler: FsiDynamicCompiler, fsiConsoleOutput: FsiConsoleOutput, fullAssemName: string - ) = + ) : Assembly MaybeNull = try // Grab the name of the assembly diff --git a/src/Compiler/Legacy/LegacyHostedCompilerForTesting.fs b/src/Compiler/Legacy/LegacyHostedCompilerForTesting.fs index 87ec46483fe..5982b97df29 100644 --- a/src/Compiler/Legacy/LegacyHostedCompilerForTesting.fs +++ b/src/Compiler/Legacy/LegacyHostedCompilerForTesting.fs @@ -208,11 +208,13 @@ type internal FscCompiler(legacyReferenceResolver) = // args.[0] is later discarded, assuming it is just the path to fsc. // compensate for this in case caller didn't know let args = - match args with - | [||] - | null -> [| "fsc" |] - | a when not <| fscExeArg a[0] -> Array.append [| "fsc" |] a - | _ -> args + match box args with + | Null -> [| "fsc" |] + | _ -> + match args with + | [||] -> [| "fsc" |] + | a when not <| fscExeArg a[0] -> Array.append [| "fsc" |] a + | _ -> args let errorRanges = args |> Seq.exists errorRangesArg let vsErrors = args |> Seq.exists vsErrorsArg diff --git a/src/Compiler/Service/IncrementalBuild.fs b/src/Compiler/Service/IncrementalBuild.fs index dc27983338e..443deca396a 100644 --- a/src/Compiler/Service/IncrementalBuild.fs +++ b/src/Compiler/Service/IncrementalBuild.fs @@ -584,9 +584,7 @@ type RawFSharpAssemblyDataBackedByLanguageService (tcConfig, tcGlobals, generate let sigData = let _sigDataAttributes, sigDataResources = EncodeSignatureData(tcConfig, tcGlobals, exportRemapping, generatedCcu, outfile, true) - [ for r in sigDataResources do - GetResourceNameAndSignatureDataFunc r - ] + GetResourceNameAndSignatureDataFuncs sigDataResources let autoOpenAttrs = topAttrs.assemblyAttrs |> List.choose (List.singleton >> TryFindFSharpStringAttribute tcGlobals tcGlobals.attrib_AutoOpenAttribute) diff --git a/src/Compiler/Service/QuickParse.fs b/src/Compiler/Service/QuickParse.fs index 381ba6a865d..dbfcbcb2931 100644 --- a/src/Compiler/Service/QuickParse.fs +++ b/src/Compiler/Service/QuickParse.fs @@ -79,7 +79,7 @@ module QuickParse = | _ -> false let GetCompleteIdentifierIslandImplAux (lineStr: string) (index: int) : (string * int * bool) option = - if index < 0 || isNull lineStr || index >= lineStr.Length then + if index < 0 || index >= lineStr.Length then None else let fixup = diff --git a/src/Compiler/Service/ServiceDeclarationLists.fs b/src/Compiler/Service/ServiceDeclarationLists.fs index a0da4745902..bd1d343c0f1 100644 --- a/src/Compiler/Service/ServiceDeclarationLists.fs +++ b/src/Compiler/Service/ServiceDeclarationLists.fs @@ -680,7 +680,7 @@ module internal DescriptionListsImpl = |> Array.map (fun sp -> let ty = Import.ImportProvidedType amap m (sp.PApply((fun x -> x.ParameterType), m)) let spKind = NicePrint.prettyLayoutOfType denv ty - let spName = sp.PUntaint((fun sp -> sp.Name), m) + let spName = sp.PUntaint((fun sp -> nonNull sp.Name), m) let spOpt = sp.PUntaint((fun sp -> sp.IsOptional), m) let display = (if spOpt then SepL.questionMark else emptyL) ^^ wordL (tagParameter spName) ^^ RightL.colon ^^ spKind let display = toArray display diff --git a/src/Compiler/Service/ServiceLexing.fs b/src/Compiler/Service/ServiceLexing.fs index 09f3d6b8016..85910118c7c 100644 --- a/src/Compiler/Service/ServiceLexing.fs +++ b/src/Compiler/Service/ServiceLexing.fs @@ -395,6 +395,9 @@ module internal TokenClassifications = | HIGH_PRECEDENCE_PAREN_APP | FIXED | HIGH_PRECEDENCE_BRACK_APP + | MAYBENULL__ + | NOTNULL__ + | WITHNULL__ | TYPE_COMING_SOON | TYPE_IS_HERE | MODULE_COMING_SOON diff --git a/src/Compiler/Service/ServiceParamInfoLocations.fs b/src/Compiler/Service/ServiceParamInfoLocations.fs index b757120b628..b9f4ddc412f 100755 --- a/src/Compiler/Service/ServiceParamInfoLocations.fs +++ b/src/Compiler/Service/ServiceParamInfoLocations.fs @@ -62,6 +62,7 @@ module internal ParameterLocationsImpl = let isStaticArg (StripParenTypes synType) = match synType with | SynType.StaticConstant _ + | SynType.StaticConstantNull _ | SynType.StaticConstantExpr _ | SynType.StaticConstantNamed _ -> true | SynType.LongIdent _ -> true // NOTE: this is not a static constant, but it is a prefix of incomplete code, e.g. "TP<42, Arg3" is a prefix of "TP<42, Arg3=6>" and Arg3 shows up as a LongId diff --git a/src/Compiler/Service/ServiceParseTreeWalk.fs b/src/Compiler/Service/ServiceParseTreeWalk.fs index b6f95d66a30..354fbf48716 100644 --- a/src/Compiler/Service/ServiceParseTreeWalk.fs +++ b/src/Compiler/Service/ServiceParseTreeWalk.fs @@ -836,6 +836,7 @@ module SyntaxTraversal = | SynType.Fun (argType = ty1; returnType = ty2) -> [ ty1; ty2 ] |> List.tryPick (traverseSynType path) | SynType.MeasurePower (ty, _, _) | SynType.HashConstraint (ty, _) + | SynType.WithNull (ty, _, _) | SynType.WithGlobalConstraints (ty, _, _) | SynType.Array (_, ty, _) -> traverseSynType path ty | SynType.StaticConstantNamed (ty1, ty2, _) @@ -844,6 +845,7 @@ module SyntaxTraversal = | SynType.StaticConstantExpr (expr, _) -> traverseSynExpr [] expr | SynType.Paren (innerType = t) | SynType.SignatureParameter (usedType = t) -> traverseSynType path t + | SynType.StaticConstantNull _ | SynType.Anon _ | SynType.AnonRecd _ | SynType.LongIdent _ diff --git a/src/Compiler/Service/ServiceParsedInputOps.fs b/src/Compiler/Service/ServiceParsedInputOps.fs index 91c48c42bcb..36343d26f97 100644 --- a/src/Compiler/Service/ServiceParsedInputOps.fs +++ b/src/Compiler/Service/ServiceParsedInputOps.fs @@ -611,6 +611,7 @@ module ParsedInput = | SynTypeConstraint.WhereTyparIsReferenceType (t, _) -> walkTypar t | SynTypeConstraint.WhereTyparIsUnmanaged (t, _) -> walkTypar t | SynTypeConstraint.WhereTyparSupportsNull (t, _) -> walkTypar t + | SynTypeConstraint.WhereTyparNotSupportsNull (t, _) -> walkTypar t | SynTypeConstraint.WhereTyparIsComparable (t, _) -> walkTypar t | SynTypeConstraint.WhereTyparIsEquatable (t, _) -> walkTypar t | SynTypeConstraint.WhereTyparSubtypeOfType (t, ty, _) -> walkTypar t |> Option.orElseWith (fun () -> walkType ty) @@ -674,6 +675,7 @@ module ParsedInput = | SynType.Array (_, t, _) -> walkType t | SynType.Fun (argType = t1; returnType = t2) -> walkType t1 |> Option.orElseWith (fun () -> walkType t2) | SynType.WithGlobalConstraints (t, _, _) -> walkType t + | SynType.WithNull (t, _, _) | SynType.HashConstraint (t, _) -> walkType t | SynType.Or (t1, t2, _, _) -> walkType t1 |> Option.orElseWith (fun () -> walkType t2) | SynType.MeasurePower (t, _, _) -> walkType t @@ -681,6 +683,7 @@ module ParsedInput = | SynType.SignatureParameter (usedType = t) -> walkType t | SynType.StaticConstantExpr (e, _) -> walkExpr e | SynType.StaticConstantNamed (ident, value, _) -> List.tryPick walkType [ ident; value ] + | SynType.StaticConstantNull _ | SynType.Anon _ | SynType.AnonRecd _ | SynType.LongIdent _ @@ -1619,6 +1622,7 @@ module ParsedInput = | SynTypeConstraint.WhereTyparIsReferenceType (t, _) | SynTypeConstraint.WhereTyparIsUnmanaged (t, _) | SynTypeConstraint.WhereTyparSupportsNull (t, _) + | SynTypeConstraint.WhereTyparNotSupportsNull (t, _) | SynTypeConstraint.WhereTyparIsComparable (t, _) | SynTypeConstraint.WhereTyparIsEquatable (t, _) -> walkTypar t | SynTypeConstraint.WhereTyparDefaultsToType (t, ty, _) @@ -1680,6 +1684,7 @@ module ParsedInput = | SynType.Array (_, t, _) | SynType.HashConstraint (t, _) | SynType.MeasurePower (t, _, _) + | SynType.WithNull (t, _, _) | SynType.Paren (t, _) | SynType.SignatureParameter (usedType = t) -> walkType t | SynType.Fun (argType = t1; returnType = t2) @@ -1699,6 +1704,7 @@ module ParsedInput = | SynType.StaticConstantNamed (ident, value, _) -> walkType ident walkType value + | SynType.StaticConstantNull _ | SynType.Anon _ | SynType.AnonRecd _ | SynType.Var _ diff --git a/src/Compiler/Symbols/Symbols.fs b/src/Compiler/Symbols/Symbols.fs index 8595d61bf1b..16823f15c14 100644 --- a/src/Compiler/Symbols/Symbols.fs +++ b/src/Compiler/Symbols/Symbols.fs @@ -1559,6 +1559,11 @@ type FSharpGenericParameterConstraint(cenv, cx: TyparConstraint) = | TyparConstraint.SupportsComparison _ -> true | _ -> false + member _.IsNotSupportsNullConstraint = + match cx with + | TyparConstraint.NotSupportsNull _ -> true + | _ -> false + member _.IsEqualityConstraint = match cx with | TyparConstraint.SupportsEquality _ -> true @@ -2459,6 +2464,23 @@ type FSharpType(cenv, ty:TType) = | TType_measure (Measure.Inv _) -> FSharpEntity(cenv, cenv.g.measureinverse_tcr) | _ -> invalidOp "not a named type" + member _.HasNullAnnotation = + protect <| fun () -> + match stripTyparEqns ty with + | TType_var (_, nullness) + | TType_app (_, _, nullness) + | TType_fun(_, _, nullness) -> match nullness.Evaluate() with NullnessInfo.WithNull -> true | _ -> false + | TType_tuple (_, _) -> false + | _ -> false + + member _.IsNullAmbivalent = + protect <| fun () -> + match stripTyparEqns ty with + | TType_app (_, _, nullness) + | TType_fun(_, _, nullness) -> match nullness.Evaluate() with NullnessInfo.AmbivalentToNull -> true | _ -> false + | TType_tuple (_, _) -> false + | _ -> false + member _.GenericArguments = protect <| fun () -> match stripTyparEqns ty with diff --git a/src/Compiler/Symbols/Symbols.fsi b/src/Compiler/Symbols/Symbols.fsi index 44e215e5214..beaa3617435 100644 --- a/src/Compiler/Symbols/Symbols.fsi +++ b/src/Compiler/Symbols/Symbols.fsi @@ -1073,6 +1073,12 @@ type FSharpType = /// Get the type definition for a type member TypeDefinition: FSharpEntity + /// Indicates this type is known to have a null annotation + member HasNullAnnotation: bool + + /// Indicates this type is assumed to support the null value + member IsNullAmbivalent: bool + /// Get the generic arguments for a tuple type, a function type or a type constructed using a named entity member GenericArguments: IList diff --git a/src/Compiler/SyntaxTree/LexFilter.fs b/src/Compiler/SyntaxTree/LexFilter.fs index e163646f688..4cdf7deda24 100644 --- a/src/Compiler/SyntaxTree/LexFilter.fs +++ b/src/Compiler/SyntaxTree/LexFilter.fs @@ -1084,7 +1084,11 @@ type LexFilterImpl ( // f<{| C : int |}>x // fx // fx + // fx + // fx + // fx | DEFAULT | COLON | COLON_GREATER | STRUCT | NULL | DELEGATE | AND | WHEN + | NOTNULL__ | MAYBENULL__ | WITHNULL__ | DOT_DOT | NEW | LBRACE_BAR diff --git a/src/Compiler/SyntaxTree/LexHelpers.fs b/src/Compiler/SyntaxTree/LexHelpers.fs index f1de8c6b814..a8723d765e7 100644 --- a/src/Compiler/SyntaxTree/LexHelpers.fs +++ b/src/Compiler/SyntaxTree/LexHelpers.fs @@ -397,6 +397,10 @@ module Keywords = FSHARP, "__token_ODO", ODO FSHARP, "__token_OLET", OLET(true) FSHARP, "__token_constraint", CONSTRAINT + (*------- for prototyping *) + FSHARP, "__maybenull", MAYBENULL__ + FSHARP, "__notnull", NOTNULL__ + FSHARP, "__withnull", WITHNULL__ ] (*------- reserved keywords which are ml-compatibility ids *) @ List.map diff --git a/src/Compiler/SyntaxTree/PrettyNaming.fs b/src/Compiler/SyntaxTree/PrettyNaming.fs index f78f742a03f..0e6d0d42102 100755 --- a/src/Compiler/SyntaxTree/PrettyNaming.fs +++ b/src/Compiler/SyntaxTree/PrettyNaming.fs @@ -1096,12 +1096,21 @@ let FSharpOptimizationDataResourceName = "FSharpOptimizationData." let FSharpSignatureDataResourceName = "FSharpSignatureData." +let FSharpOptimizationDataResourceNameB = "FSharpOptimizationDataB." + +let FSharpSignatureDataResourceNameB = "FSharpSignatureDataB." + // Compressed OptimizationData/SignatureData name for embedded resource let FSharpOptimizationCompressedDataResourceName = "FSharpOptimizationCompressedData." let FSharpSignatureCompressedDataResourceName = "FSharpSignatureCompressedData." +let FSharpOptimizationCompressedDataResourceNameB = + "FSharpOptimizationCompressedDataB." + +let FSharpSignatureCompressedDataResourceNameB = "FSharpSignatureCompressedDataB." + // For historical reasons, we use a different resource name for FSharp.Core, so older F# compilers // don't complain when they see the resource. The prefix of these names must not be 'FSharpOptimizationData' // or 'FSharpSignatureData' diff --git a/src/Compiler/SyntaxTree/PrettyNaming.fsi b/src/Compiler/SyntaxTree/PrettyNaming.fsi index 05478070e1a..27f6f2e0ea3 100644 --- a/src/Compiler/SyntaxTree/PrettyNaming.fsi +++ b/src/Compiler/SyntaxTree/PrettyNaming.fsi @@ -267,10 +267,18 @@ val internal FSharpOptimizationDataResourceName: string val internal FSharpSignatureDataResourceName: string +val internal FSharpOptimizationDataResourceNameB: string + +val internal FSharpSignatureDataResourceNameB: string + val internal FSharpOptimizationCompressedDataResourceName: string val internal FSharpSignatureCompressedDataResourceName: string +val internal FSharpOptimizationCompressedDataResourceNameB: string + +val internal FSharpSignatureCompressedDataResourceNameB: string + val internal FSharpOptimizationDataResourceName2: string val internal FSharpSignatureDataResourceName2: string diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs index eb8c30d2c03..a7360d0165e 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fs +++ b/src/Compiler/SyntaxTree/SyntaxTree.fs @@ -322,6 +322,8 @@ type SynTypeConstraint = | WhereTyparSupportsNull of typar: SynTypar * range: range + | WhereTyparNotSupportsNull of genericName: SynTypar * range: range + | WhereTyparIsComparable of typar: SynTypar * range: range | WhereTyparIsEquatable of typar: SynTypar * range: range @@ -344,6 +346,7 @@ type SynTypeConstraint = | WhereTyparIsReferenceType (range = range) | WhereTyparIsUnmanaged (range = range) | WhereTyparSupportsNull (range = range) + | WhereTyparNotSupportsNull (range = range) | WhereTyparIsComparable (range = range) | WhereTyparIsEquatable (range = range) | WhereTyparDefaultsToType (range = range) @@ -431,10 +434,14 @@ type SynType = | StaticConstant of constant: SynConst * range: range + | StaticConstantNull of range: range + | StaticConstantExpr of expr: SynExpr * range: range | StaticConstantNamed of ident: SynType * value: SynType * range: range + | WithNull of innerType: SynType * ambivalent: bool * range: range + | Paren of innerType: SynType * range: range | SignatureParameter of attributes: SynAttributes * optional: bool * id: Ident option * usedType: SynType * range: range @@ -455,9 +462,11 @@ type SynType = | SynType.Anon (range = m) | SynType.WithGlobalConstraints (range = m) | SynType.StaticConstant (range = m) + | SynType.StaticConstantNull (range = m) | SynType.StaticConstantExpr (range = m) | SynType.StaticConstantNamed (range = m) | SynType.HashConstraint (range = m) + | SynType.WithNull (range = m) | SynType.MeasurePower (range = m) | SynType.Paren (range = m) | SynType.SignatureParameter (range = m) diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi index 5c35a2e2c82..9ba3e480d81 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi @@ -392,6 +392,9 @@ type SynTypeConstraint = /// F# syntax is 'typar: null | WhereTyparSupportsNull of typar: SynTypar * range: range + /// F# syntax is 'typar : null + | WhereTyparNotSupportsNull of genericName: SynTypar * range: range + /// F# syntax is 'typar: comparison | WhereTyparIsComparable of typar: SynTypar * range: range @@ -499,12 +502,17 @@ type SynType = /// For the dimensionless units i.e. 1, and static parameters to provided types | StaticConstant of constant: SynConst * range: range + /// F# syntax: null, used in parameters to type providers + | StaticConstantNull of range: range + /// F# syntax: const expr, used in static parameters to type providers | StaticConstantExpr of expr: SynExpr * range: range /// F# syntax: ident=1 etc., used in static parameters to type providers | StaticConstantNamed of ident: SynType * value: SynType * range: range + | WithNull of innerType: SynType * ambivalent: bool * range: range + | Paren of innerType: SynType * range: range /// F# syntax: a: b, used in signatures and type annotations diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs index 4174d567a6e..3f92f88a3e6 100755 --- a/src/Compiler/TypedTree/TcGlobals.fs +++ b/src/Compiler/TypedTree/TcGlobals.fs @@ -185,6 +185,7 @@ type TcGlobals( directoryToResolveRelativePaths, mlCompatibility: bool, isInteractive: bool, + checkNullness: bool, useReflectionFreeCodeGen: bool, // The helper to find system types amongst referenced DLLs tryFindSysTypeCcuHelper, @@ -193,11 +194,15 @@ type TcGlobals( pathMap: PathMap, langVersion: LanguageVersion) = - // empty flags - let v_knownWithoutNull = 0uy + let v_langFeatureNullness = langVersion.SupportsFeature LanguageFeature.NullnessChecking + + let v_knownWithoutNull = + if v_langFeatureNullness then KnownWithoutNull else KnownAmbivalentToNull let mkNonGenericTy tcref = TType_app(tcref, [], v_knownWithoutNull) + let mkNonGenericTyWithNullness tcref nullness = TType_app(tcref, [], nullness) + let mkNonLocalTyconRef2 ccu path n = mkNonLocalTyconRef (mkNonLocalEntityRef ccu path) n let mk_MFCore_tcref ccu n = mkNonLocalTyconRef2 ccu CorePathArray n @@ -642,16 +647,18 @@ type TcGlobals( | [_] -> None | _ -> TType_tuple (tupInfo, l) |> Some - - let decodeTupleTy tupInfo l = - match tryDecodeTupleTy tupInfo l with + let decodeTupleTyAndNullness tupInfo tinst _nullness = // TODO nullness + match tryDecodeTupleTy tupInfo tinst with | Some ty -> ty | None -> failwith "couldn't decode tuple ty" - let decodeTupleTyIfPossible tcref tupInfo l = - match tryDecodeTupleTy tupInfo l with + let decodeTupleTyAndNullnessIfPossible tcref tupInfo tinst nullness = // TODO nullness + match tryDecodeTupleTy tupInfo tinst with | Some ty -> ty - | None -> TType_app(tcref, l, v_knownWithoutNull) + | None -> TType_app(tcref, tinst, nullness) + + let decodeTupleTy tupInfo tinst = + decodeTupleTyAndNullness tupInfo tinst v_knownWithoutNull let mk_MFCore_attrib nm : BuiltinAttribInfo = AttribInfo(mkILTyRef(ilg.fsharpCoreAssemblyScopeRef, Core + "." + nm), mk_MFCore_tcref fslibCcu nm) @@ -948,25 +955,29 @@ type TcGlobals( "Single" , v_float32_tcr |] |> Array.map (fun (nm, tcr) -> let ty = mkNonGenericTy tcr - nm, findSysTyconRef sys nm, (fun _ -> ty)) + nm, findSysTyconRef sys nm, (fun _ nullness -> + match nullness with + | Nullness.Known NullnessInfo.WithoutNull -> ty + | _ -> mkNonGenericTyWithNullness tcr nullness)) let decompileTyconEntries = [| - "FSharpFunc`2" , v_fastFunc_tcr , (fun tinst -> mkFunTy (List.item 0 tinst) (List.item 1 tinst)) - "Tuple`2" , v_ref_tuple2_tcr , decodeTupleTy tupInfoRef - "Tuple`3" , v_ref_tuple3_tcr , decodeTupleTy tupInfoRef - "Tuple`4" , v_ref_tuple4_tcr , decodeTupleTy tupInfoRef - "Tuple`5" , v_ref_tuple5_tcr , decodeTupleTy tupInfoRef - "Tuple`6" , v_ref_tuple6_tcr , decodeTupleTy tupInfoRef - "Tuple`7" , v_ref_tuple7_tcr , decodeTupleTy tupInfoRef - "Tuple`8" , v_ref_tuple8_tcr , decodeTupleTyIfPossible v_ref_tuple8_tcr tupInfoRef - "ValueTuple`2" , v_struct_tuple2_tcr , decodeTupleTy tupInfoStruct - "ValueTuple`3" , v_struct_tuple3_tcr , decodeTupleTy tupInfoStruct - "ValueTuple`4" , v_struct_tuple4_tcr , decodeTupleTy tupInfoStruct - "ValueTuple`5" , v_struct_tuple5_tcr , decodeTupleTy tupInfoStruct - "ValueTuple`6" , v_struct_tuple6_tcr , decodeTupleTy tupInfoStruct - "ValueTuple`7" , v_struct_tuple7_tcr , decodeTupleTy tupInfoStruct - "ValueTuple`8" , v_struct_tuple8_tcr , decodeTupleTyIfPossible v_struct_tuple8_tcr tupInfoStruct |] + // TODO: nullness here + "FSharpFunc`2" , v_fastFunc_tcr , (fun tinst _nullness -> mkFunTy (List.item 0 tinst) (List.item 1 tinst)) + "Tuple`2" , v_ref_tuple2_tcr , decodeTupleTyAndNullness tupInfoRef + "Tuple`3" , v_ref_tuple3_tcr , decodeTupleTyAndNullness tupInfoRef + "Tuple`4" , v_ref_tuple4_tcr , decodeTupleTyAndNullness tupInfoRef + "Tuple`5" , v_ref_tuple5_tcr , decodeTupleTyAndNullness tupInfoRef + "Tuple`6" , v_ref_tuple6_tcr , decodeTupleTyAndNullness tupInfoRef + "Tuple`7" , v_ref_tuple7_tcr , decodeTupleTyAndNullness tupInfoRef + "Tuple`8" , v_ref_tuple8_tcr , decodeTupleTyAndNullnessIfPossible v_ref_tuple8_tcr tupInfoRef + "ValueTuple`2" , v_struct_tuple2_tcr , decodeTupleTyAndNullness tupInfoStruct + "ValueTuple`3" , v_struct_tuple3_tcr , decodeTupleTyAndNullness tupInfoStruct + "ValueTuple`4" , v_struct_tuple4_tcr , decodeTupleTyAndNullness tupInfoStruct + "ValueTuple`5" , v_struct_tuple5_tcr , decodeTupleTyAndNullness tupInfoStruct + "ValueTuple`6" , v_struct_tuple6_tcr , decodeTupleTyAndNullness tupInfoStruct + "ValueTuple`7" , v_struct_tuple7_tcr , decodeTupleTyAndNullness tupInfoStruct + "ValueTuple`8" , v_struct_tuple8_tcr , decodeTupleTyAndNullnessIfPossible v_struct_tuple8_tcr tupInfoStruct |] let betterEntries = Array.append betterTyconEntries decompileTyconEntries @@ -997,11 +1008,11 @@ type TcGlobals( let t = Dictionary.newWithSize entries.Length for nm, tcref, builder in entries do t.Add(nm, - (fun tcref2 tinst2 -> + (fun tcref2 tinst2 nullness -> if tyconRefEq tcref tcref2 then - builder tinst2 + builder tinst2 nullness else - TType_app (tcref2, tinst2, v_knownWithoutNull))) + TType_app (tcref2, tinst2, nullness))) betterTypeDict1 <- t t | _ -> betterTypeDict1 @@ -1023,30 +1034,30 @@ type TcGlobals( /// For logical purposes equate some F# types with .NET types, e.g. TType_tuple == System.Tuple/ValueTuple. /// Doing this normalization is a fairly performance critical piece of code as it is frequently invoked /// in the process of converting .NET metadata to F# internal compiler data structures (see import.fs). - let decompileTy (tcref: EntityRef) tinst = + let decompileTy (tcref: EntityRef) tinst nullness = if compilingFSharpCore then // No need to decompile when compiling FSharp.Core.dll - TType_app (tcref, tinst, v_knownWithoutNull) + TType_app (tcref, tinst, nullness) else let dict = getDecompileTypeDict() match dict.TryGetValue tcref.Stamp with - | true, builder -> builder tinst - | _ -> TType_app (tcref, tinst, v_knownWithoutNull) + | true, builder -> builder tinst nullness + | _ -> TType_app (tcref, tinst, nullness) /// For cosmetic purposes "improve" some .NET types, e.g. Int32 --> int32. /// Doing this normalization is a fairly performance critical piece of code as it is frequently invoked /// in the process of converting .NET metadata to F# internal compiler data structures (see import.fs). - let improveTy (tcref: EntityRef) tinst = + let improveTy (tcref: EntityRef) tinst nullness = if compilingFSharpCore then let dict = getBetterTypeDict1() match dict.TryGetValue tcref.LogicalName with - | true, builder -> builder tcref tinst - | _ -> TType_app (tcref, tinst, v_knownWithoutNull) + | true, builder -> builder tcref tinst nullness + | _ -> TType_app (tcref, tinst, nullness) else let dict = getBetterTypeDict2() match dict.TryGetValue tcref.Stamp with - | true, builder -> builder tinst - | _ -> TType_app (tcref, tinst, v_knownWithoutNull) + | true, builder -> builder tinst nullness + | _ -> TType_app (tcref, tinst, nullness) // Adding an unnecessary "let" instead of inlining into a muiti-line pipelined compute-once "member val" that is too complex for @dsyme let v_attribs_Unsupported = [ @@ -1076,7 +1087,10 @@ type TcGlobals( // A table of all intrinsics that the compiler cares about member _.knownIntrinsics = v_knownIntrinsics - // empty flags + member _.checkNullness = checkNullness + + member _.langFeatureNullness = v_langFeatureNullness + member _.knownWithoutNull = v_knownWithoutNull // A table of known modules in FSharp.Core. Not all modules are necessarily listed, but the more we list the diff --git a/src/Compiler/TypedTree/TypeProviders.fs b/src/Compiler/TypedTree/TypeProviders.fs index dff177e296f..fbb1899bcd1 100644 --- a/src/Compiler/TypedTree/TypeProviders.fs +++ b/src/Compiler/TypedTree/TypeProviders.fs @@ -227,8 +227,13 @@ let TryTypeMemberArray (st: Tainted<_>, fullName, memberName, m, f) = [||] /// Try to access a member on a provided type, catching and reporting errors and checking the result is non-null, +#if NO_CHECKNULLS let TryTypeMemberNonNull<'T, 'U when 'U : null and 'U : not struct>(st: Tainted<'T>, fullName, memberName, m, recover: 'U, (f: 'T -> 'U)) : Tainted<'U> = match TryTypeMember(st, fullName, memberName, m, recover, f) with +#else +let TryTypeMemberNonNull<'T, 'U when 'U : __notnull and 'U : not struct>(st: Tainted<'T>, fullName, memberName, m, recover: 'U, (f: 'T -> 'U __withnull)) : Tainted<'U> = + match TryTypeMember<'T, 'U __withnull>(st, fullName, memberName, m, withNull recover, f) with +#endif | Tainted.Null -> errorR(Error(FSComp.SR.etUnexpectedNullFromProvidedTypeMember(fullName, memberName), m)) st.PApplyNoFailure(fun _ -> recover) @@ -338,7 +343,10 @@ type ProvidedTypeContext = for KeyValue (st, tcref) in d2.Force() do dict.TryAdd(st, f tcref) |> ignore dict)) -[] +[] +#if NO_CHECKNULLS +[] +#endif type ProvidedType (x: Type, ctxt: ProvidedTypeContext) = inherit ProvidedMemberInfo(x, ctxt) @@ -406,7 +414,7 @@ type ProvidedType (x: Type, ctxt: ProvidedTypeContext) = /// Type.BaseType can be null when Type is interface or object member _.BaseType = x.BaseType |> ProvidedType.Create ctxt - member _.GetStaticParameters(provider: ITypeProvider) = provider.GetStaticParameters x |> ProvidedParameterInfo.CreateArray ctxt + member _.GetStaticParameters(provider: ITypeProvider) : ProvidedParameterInfo[] MaybeNull = provider.GetStaticParameters x |> ProvidedParameterInfo.CreateArray ctxt /// Type.GetElementType can be null if i.e. Type is not array\pointer\byref type member _.GetElementType() = x.GetElementType() |> ProvidedType.Create ctxt @@ -465,17 +473,28 @@ type ProvidedType (x: Type, ctxt: ProvidedTypeContext) = let argTypes = args |> Array.map (fun arg -> arg.RawSystemType) ProvidedType.CreateNoContext(x.MakeGenericType(argTypes)) - member _.AsProvidedVar name = ProvidedVar.Create ctxt (Var(name, x)) + member _.AsProvidedVar name = ProvidedVar.CreateNonNull ctxt (Quotations.Var(name, x)) + + static member Create ctxt x : ProvidedType MaybeNull = + match x with + | Null -> null + | NonNull t -> ProvidedType (t, ctxt) - static member Create ctxt x = match x with null -> null | t -> ProvidedType (t, ctxt) + static member CreateNonNull ctxt x = ProvidedType (x, ctxt) - static member CreateWithNullCheck ctxt name x = match x with null -> nullArg name | t -> ProvidedType (t, ctxt) + static member CreateWithNullCheck ctxt name x = + match x with + | Null -> nullArg name + | t -> ProvidedType (t, ctxt) - static member CreateArray ctxt xs = match xs with null -> null | _ -> xs |> Array.map (ProvidedType.Create ctxt) + static member CreateArray ctxt (xs: Type[] MaybeNull) : ProvidedType[] MaybeNull = + match xs with + | Null -> null + | NonNull xs -> xs |> Array.map (ProvidedType.CreateNonNull ctxt) - static member CreateNoContext (x: Type) = ProvidedType.Create ProvidedTypeContext.Empty x + static member CreateNoContext (x:Type) = ProvidedType.Create ProvidedTypeContext.Empty x - static member Void = ProvidedType.CreateNoContext typeof + static member Void = ProvidedType.CreateNoContext typeof member _.Handle = x @@ -494,12 +513,17 @@ type ProvidedType (x: Type, ctxt: ProvidedTypeContext) = static member TaintedEquals (pt1: Tainted, pt2: Tainted) = Tainted.EqTainted (pt1.PApplyNoFailure(fun st -> st.Handle)) (pt2.PApplyNoFailure(fun st -> st.Handle)) -[] +#if NO_CHECKNULLS +[] +#endif type IProvidedCustomAttributeProvider = - abstract GetDefinitionLocationAttribute: provider: ITypeProvider -> (string * int * int) option - abstract GetXmlDocAttributes: provider: ITypeProvider -> string[] - abstract GetHasTypeProviderEditorHideMethodsAttribute: provider: ITypeProvider -> bool - abstract GetAttributeConstructorArgs: provider: ITypeProvider * attribName: string -> (obj option list * (string * obj option) list) option + abstract GetDefinitionLocationAttribute : provider: ITypeProvider -> (string MaybeNull * int * int) option + + abstract GetXmlDocAttributes : provider: ITypeProvider -> string[] + + abstract GetHasTypeProviderEditorHideMethodsAttribute : provider:ITypeProvider -> bool + + abstract GetAttributeConstructorArgs: provider:ITypeProvider * attribName:string -> (obj option list * (string * obj option) list) option type ProvidedCustomAttributeProvider (attributes :ITypeProvider -> seq) = let (|Member|_|) (s: string) (x: CustomAttributeNamedArgument) = if x.MemberName = s then Some x.TypedValue else None @@ -529,7 +553,7 @@ type ProvidedCustomAttributeProvider (attributes :ITypeProvider -> seq Seq.tryFind (findAttrib typeof) |> Option.map (fun a -> - let filePath = defaultArg (a.NamedArguments |> Seq.tryPick (function Member "FilePath" (Arg (:? string as v)) -> Some v | _ -> None)) null + let filePath : string MaybeNull = defaultArg (a.NamedArguments |> Seq.tryPick (function Member "FilePath" (Arg (:? string as v)) -> Some v | _ -> None)) null let line = defaultArg (a.NamedArguments |> Seq.tryPick (function Member "Line" (Arg (:? int as v)) -> Some v | _ -> None)) 0 let column = defaultArg (a.NamedArguments |> Seq.tryPick (function Member "Column" (Arg (:? int as v)) -> Some v | _ -> None)) 0 (filePath, line, column)) @@ -545,7 +569,10 @@ type ProvidedCustomAttributeProvider (attributes :ITypeProvider -> seq Seq.toArray -[] +[] +#if NO_CHECKNULLS +[] +#endif type ProvidedMemberInfo (x: MemberInfo, ctxt) = let provide () = ProvidedCustomAttributeProvider (fun _ -> x.CustomAttributes) :> IProvidedCustomAttributeProvider @@ -567,11 +594,14 @@ type ProvidedMemberInfo (x: MemberInfo, ctxt) = member _.GetAttributeConstructorArgs (provider, attribName) = provide().GetAttributeConstructorArgs (provider, attribName) -[] +[] +#if NO_CHECKNULLS +[] +#endif type ProvidedParameterInfo (x: ParameterInfo, ctxt) = let provide () = ProvidedCustomAttributeProvider (fun _ -> x.CustomAttributes) :> IProvidedCustomAttributeProvider - member _.Name = x.Name + member _.Name = let nm = x.Name in match box nm with null -> "" | _ -> nm member _.IsOut = x.IsOut @@ -584,12 +614,25 @@ type ProvidedParameterInfo (x: ParameterInfo, ctxt) = member _.HasDefaultValue = x.Attributes.HasFlag(ParameterAttributes.HasDefault) /// ParameterInfo.ParameterType cannot be null - member _.ParameterType = ProvidedType.CreateWithNullCheck ctxt "ParameterType" x.ParameterType - - static member Create ctxt x = match x with null -> null | t -> ProvidedParameterInfo (t, ctxt) - - static member CreateArray ctxt xs = match xs with null -> null | _ -> xs |> Array.map (ProvidedParameterInfo.Create ctxt) // TODO null wrong? - + member _.ParameterType = ProvidedType.CreateWithNullCheck ctxt "ParameterType" x.ParameterType + + static member Create ctxt (x: ParameterInfo MaybeNull) : ProvidedParameterInfo MaybeNull = + match x with + | Null -> null + | NonNull x -> ProvidedParameterInfo (x, ctxt) + + static member CreateNonNull ctxt x = ProvidedParameterInfo (x, ctxt) + + static member CreateArray ctxt (xs: ParameterInfo[] MaybeNull) : ProvidedParameterInfo[] MaybeNull = + match xs with + | Null -> null + | NonNull xs -> xs |> Array.map (ProvidedParameterInfo.CreateNonNull ctxt) + + static member CreateArrayNonNull ctxt xs : ProvidedParameterInfo[] = + match box xs with + | Null -> [| |] + | _ -> xs |> Array.map (ProvidedParameterInfo.CreateNonNull ctxt) + interface IProvidedCustomAttributeProvider with member _.GetHasTypeProviderEditorHideMethodsAttribute provider = provide().GetHasTypeProviderEditorHideMethodsAttribute provider @@ -609,7 +652,10 @@ type ProvidedParameterInfo (x: ParameterInfo, ctxt) = override _.GetHashCode() = assert false; x.GetHashCode() -[] +[] +#if NO_CHECKNULLS +[] +#endif type ProvidedAssembly (x: Assembly) = member _.GetName() = x.GetName() @@ -618,7 +664,7 @@ type ProvidedAssembly (x: Assembly) = member _.GetManifestModuleContents(provider: ITypeProvider) = provider.GetGeneratedAssemblyContents x - static member Create (x: Assembly) = match x with null -> null | t -> ProvidedAssembly t + static member Create x : ProvidedAssembly MaybeNull = match x with null -> null | t -> ProvidedAssembly (t) member _.Handle = x @@ -626,7 +672,10 @@ type ProvidedAssembly (x: Assembly) = override _.GetHashCode() = assert false; x.GetHashCode() -[] +[] +#if NO_CHECKNULLS +[] +#endif type ProvidedMethodBase (x: MethodBase, ctxt) = inherit ProvidedMemberInfo(x, ctxt) @@ -661,12 +710,14 @@ type ProvidedMethodBase (x: MethodBase, ctxt) = member _.Handle = x static member TaintedGetHashCode (x: Tainted) = - Tainted.GetHashCodeTainted (x.PApplyNoFailure(fun st -> (st.Name, st.DeclaringType.Assembly.FullName, st.DeclaringType.FullName))) + Tainted.GetHashCodeTainted + (x.PApplyNoFailure(fun st -> (st.Name, (nonNull (nonNull st.DeclaringType).Assembly).FullName, + (nonNull st.DeclaringType).FullName))) static member TaintedEquals (pt1: Tainted, pt2: Tainted) = Tainted.EqTainted (pt1.PApplyNoFailure(fun st -> st.Handle)) (pt2.PApplyNoFailure(fun st -> st.Handle)) - member _.GetStaticParametersForMethod(provider: ITypeProvider) = + member _.GetStaticParametersForMethod(provider: ITypeProvider) : ProvidedParameterInfo[] = let bindingFlags = BindingFlags.Instance ||| BindingFlags.NonPublic ||| BindingFlags.Public let staticParams = @@ -685,7 +736,7 @@ type ProvidedMethodBase (x: MethodBase, ctxt) = with err -> raise (StripException (StripException err)) paramsAsObj :?> ParameterInfo[] - staticParams |> ProvidedParameterInfo.CreateArray ctxt + staticParams |> ProvidedParameterInfo.CreateArrayNonNull ctxt member _.ApplyStaticArgumentsForMethod(provider: ITypeProvider, fullNameAfterArguments: string, staticArgs: obj[]) = let bindingFlags = BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.InvokeMethod @@ -702,7 +753,7 @@ type ProvidedMethodBase (x: MethodBase, ctxt) = [| typeof; typeof; typeof |], null) match meth with - | null -> failwith (FSComp.SR.estApplyStaticArgumentsForMethodNotImplemented()) + | Null -> failwith (FSComp.SR.estApplyStaticArgumentsForMethodNotImplemented()) | _ -> let mbAsObj = try meth.Invoke(provider, bindingFlags ||| BindingFlags.InvokeMethod, null, [| box x; box fullNameAfterArguments; box staticArgs |], null) @@ -712,18 +763,29 @@ type ProvidedMethodBase (x: MethodBase, ctxt) = | :? MethodBase as mb -> mb | _ -> failwith (FSComp.SR.estApplyStaticArgumentsForMethodNotImplemented()) match mb with - | :? MethodInfo as mi -> (mi |> ProvidedMethodInfo.Create ctxt: ProvidedMethodInfo) :> ProvidedMethodBase - | :? ConstructorInfo as ci -> (ci |> ProvidedConstructorInfo.Create ctxt: ProvidedConstructorInfo) :> ProvidedMethodBase + | :? MethodInfo as mi -> (mi |> ProvidedMethodInfo.CreateNonNull ctxt : ProvidedMethodInfo) :> ProvidedMethodBase + | :? ConstructorInfo as ci -> (ci |> ProvidedConstructorInfo.CreateNonNull ctxt : ProvidedConstructorInfo) :> ProvidedMethodBase | _ -> failwith (FSComp.SR.estApplyStaticArgumentsForMethodNotImplemented()) -[] +[] +#if NO_CHECKNULLS +[] +#endif type ProvidedFieldInfo (x: FieldInfo, ctxt) = inherit ProvidedMemberInfo(x, ctxt) - static member Create ctxt x = match x with null -> null | t -> ProvidedFieldInfo (t, ctxt) + static member CreateNonNull ctxt x = ProvidedFieldInfo (x, ctxt) + + static member Create ctxt x : ProvidedFieldInfo MaybeNull = + match x with + | Null -> null + | NonNull x -> ProvidedFieldInfo (x, ctxt) - static member CreateArray ctxt xs = match xs with null -> null | _ -> xs |> Array.map (ProvidedFieldInfo.Create ctxt) + static member CreateArray ctxt (xs: FieldInfo[] MaybeNull) : ProvidedFieldInfo[] MaybeNull = + match xs with + | Null -> null + | NonNull xs -> xs |> Array.map (ProvidedFieldInfo.CreateNonNull ctxt) member _.IsInitOnly = x.IsInitOnly @@ -758,15 +820,27 @@ type ProvidedFieldInfo (x: FieldInfo, ctxt) = static member TaintedEquals (pt1: Tainted, pt2: Tainted) = Tainted.EqTainted (pt1.PApplyNoFailure(fun st -> st.Handle)) (pt2.PApplyNoFailure(fun st -> st.Handle)) -[] +[] +#if NO_CHECKNULLS +[] +#endif type ProvidedMethodInfo (x: MethodInfo, ctxt) = inherit ProvidedMethodBase(x, ctxt) member _.ReturnType = x.ReturnType |> ProvidedType.CreateWithNullCheck ctxt "ReturnType" - static member Create ctxt x = match x with null -> null | t -> ProvidedMethodInfo (t, ctxt) + static member CreateNonNull ctxt (x: MethodInfo) : ProvidedMethodInfo = + ProvidedMethodInfo (x, ctxt) + + static member Create ctxt (x: MethodInfo MaybeNull) : ProvidedMethodInfo MaybeNull = + match x with + | Null -> null + | NonNull x -> ProvidedMethodInfo (x, ctxt) - static member CreateArray ctxt xs = match xs with null -> null | _ -> xs |> Array.map (ProvidedMethodInfo.Create ctxt) + static member CreateArray ctxt (xs: MethodInfo[] MaybeNull) : ProvidedMethodInfo[] MaybeNull = + match xs with + | Null -> null + | NonNull xs -> xs |> Array.map (ProvidedMethodInfo.CreateNonNull ctxt) member _.Handle = x @@ -776,7 +850,10 @@ type ProvidedMethodInfo (x: MethodInfo, ctxt) = override _.GetHashCode() = assert false; x.GetHashCode() -[] +[] +#if NO_CHECKNULLS +[] +#endif type ProvidedPropertyInfo (x: PropertyInfo, ctxt) = inherit ProvidedMemberInfo(x, ctxt) @@ -793,9 +870,17 @@ type ProvidedPropertyInfo (x: PropertyInfo, ctxt) = /// PropertyInfo.PropertyType cannot be null member _.PropertyType = x.PropertyType |> ProvidedType.CreateWithNullCheck ctxt "PropertyType" - static member Create ctxt x = match x with null -> null | t -> ProvidedPropertyInfo (t, ctxt) + static member CreateNonNull ctxt x = ProvidedPropertyInfo (x, ctxt) + + static member Create ctxt x : ProvidedPropertyInfo MaybeNull = + match x with + | Null -> null + | NonNull x -> ProvidedPropertyInfo (x, ctxt) - static member CreateArray ctxt xs = match xs with null -> null | _ -> xs |> Array.map (ProvidedPropertyInfo.Create ctxt) + static member CreateArray ctxt (xs: PropertyInfo[] MaybeNull) : ProvidedPropertyInfo[] MaybeNull = + match xs with + | Null -> null + | NonNull xs -> xs |> Array.map (ProvidedPropertyInfo.CreateNonNull ctxt) member _.Handle = x @@ -804,12 +889,17 @@ type ProvidedPropertyInfo (x: PropertyInfo, ctxt) = override _.GetHashCode() = assert false; x.GetHashCode() static member TaintedGetHashCode (x: Tainted) = - Tainted.GetHashCodeTainted (x.PApplyNoFailure(fun st -> (st.Name, st.DeclaringType.Assembly.FullName, st.DeclaringType.FullName))) + Tainted.GetHashCodeTainted + (x.PApplyNoFailure(fun st -> (st.Name, (nonNull (nonNull st.DeclaringType).Assembly).FullName, + (nonNull st.DeclaringType).FullName))) static member TaintedEquals (pt1: Tainted, pt2: Tainted) = Tainted.EqTainted (pt1.PApplyNoFailure(fun st -> st.Handle)) (pt2.PApplyNoFailure(fun st -> st.Handle)) -[] +[] +#if NO_CHECKNULLS +[] +#endif type ProvidedEventInfo (x: EventInfo, ctxt) = inherit ProvidedMemberInfo(x, ctxt) @@ -819,11 +909,19 @@ type ProvidedEventInfo (x: EventInfo, ctxt) = /// EventInfo.EventHandlerType cannot be null member _.EventHandlerType = x.EventHandlerType |> ProvidedType.CreateWithNullCheck ctxt "EventHandlerType" - - static member Create ctxt x = match x with null -> null | t -> ProvidedEventInfo (t, ctxt) - - static member CreateArray ctxt xs = match xs with null -> null | _ -> xs |> Array.map (ProvidedEventInfo.Create ctxt) - + + static member CreateNonNull ctxt x = ProvidedEventInfo (x, ctxt) + + static member Create ctxt x : ProvidedEventInfo MaybeNull = + match x with + | Null -> null + | NonNull x -> ProvidedEventInfo (x, ctxt) + + static member CreateArray ctxt (xs: EventInfo[] MaybeNull) : ProvidedEventInfo[] MaybeNull = + match xs with + | Null -> null + | NonNull xs -> xs |> Array.map (ProvidedEventInfo.CreateNonNull ctxt) + member _.Handle = x override _.Equals y = assert false; match y with :? ProvidedEventInfo as y -> x.Equals y.Handle | _ -> false @@ -831,18 +929,31 @@ type ProvidedEventInfo (x: EventInfo, ctxt) = override _.GetHashCode() = assert false; x.GetHashCode() static member TaintedGetHashCode (x: Tainted) = - Tainted.GetHashCodeTainted (x.PApplyNoFailure(fun st -> (st.Name, st.DeclaringType.Assembly.FullName, st.DeclaringType.FullName))) + Tainted.GetHashCodeTainted + (x.PApplyNoFailure(fun st -> (st.Name, (nonNull (nonNull st.DeclaringType).Assembly).FullName, + (nonNull st.DeclaringType).FullName))) static member TaintedEquals (pt1: Tainted, pt2: Tainted) = Tainted.EqTainted (pt1.PApplyNoFailure(fun st -> st.Handle)) (pt2.PApplyNoFailure(fun st -> st.Handle)) -[] +[] +#if NO_CHECKNULLS +[] +#endif type ProvidedConstructorInfo (x: ConstructorInfo, ctxt) = inherit ProvidedMethodBase(x, ctxt) - static member Create ctxt x = match x with null -> null | t -> ProvidedConstructorInfo (t, ctxt) + static member CreateNonNull ctxt x = ProvidedConstructorInfo (x, ctxt) + + static member Create ctxt (x: ConstructorInfo MaybeNull) : ProvidedConstructorInfo MaybeNull = + match x with + | Null -> null + | NonNull x -> ProvidedConstructorInfo (x, ctxt) - static member CreateArray ctxt xs = match xs with null -> null | _ -> xs |> Array.map (ProvidedConstructorInfo.Create ctxt) + static member CreateArray ctxt (xs: ConstructorInfo[] MaybeNull) : ProvidedConstructorInfo[] MaybeNull = + match xs with + | Null -> null + | NonNull xs -> xs |> Array.map (ProvidedConstructorInfo.CreateNonNull ctxt) member _.Handle = x @@ -875,7 +986,11 @@ type ProvidedExprType = | ProvidedIfThenElseExpr of ProvidedExpr * ProvidedExpr * ProvidedExpr | ProvidedVarExpr of ProvidedVar +#if NO_CHECKNULLS [] +#else +[] +#endif type ProvidedExpr (x: Expr, ctxt) = member _.Type = x.Type |> ProvidedType.Create ctxt @@ -889,74 +1004,94 @@ type ProvidedExpr (x: Expr, ctxt) = member _.GetExprType() = match x with | Patterns.NewObject(ctor, args) -> - Some (ProvidedNewObjectExpr (ProvidedConstructorInfo.Create ctxt ctor, [| for a in args -> ProvidedExpr.Create ctxt a |])) + Some (ProvidedNewObjectExpr (ProvidedConstructorInfo.CreateNonNull ctxt ctor, [| for a in args -> ProvidedExpr.CreateNonNull ctxt a |])) | Patterns.WhileLoop(guardExpr, bodyExpr) -> - Some (ProvidedWhileLoopExpr (ProvidedExpr.Create ctxt guardExpr, ProvidedExpr.Create ctxt bodyExpr)) + Some (ProvidedWhileLoopExpr (ProvidedExpr.CreateNonNull ctxt guardExpr, ProvidedExpr.CreateNonNull ctxt bodyExpr)) | Patterns.NewDelegate(ty, vs, expr) -> - Some (ProvidedNewDelegateExpr(ProvidedType.Create ctxt ty, ProvidedVar.CreateArray ctxt (List.toArray vs), ProvidedExpr.Create ctxt expr)) + Some (ProvidedNewDelegateExpr(ProvidedType.CreateNonNull ctxt ty, ProvidedVar.CreateArray ctxt (List.toArray vs), ProvidedExpr.CreateNonNull ctxt expr)) | Patterns.Call(objOpt, meth, args) -> - Some (ProvidedCallExpr((match objOpt with None -> None | Some obj -> Some (ProvidedExpr.Create ctxt obj)), - ProvidedMethodInfo.Create ctxt meth, [| for a in args -> ProvidedExpr.Create ctxt a |])) + Some (ProvidedCallExpr((match objOpt with None -> None | Some obj -> Some (ProvidedExpr.CreateNonNull ctxt obj)), + ProvidedMethodInfo.CreateNonNull ctxt meth, [| for a in args -> ProvidedExpr.CreateNonNull ctxt a |])) | Patterns.DefaultValue ty -> - Some (ProvidedDefaultExpr (ProvidedType.Create ctxt ty)) + Some (ProvidedDefaultExpr (ProvidedType.CreateNonNull ctxt ty)) | Patterns.Value(obj, ty) -> - Some (ProvidedConstantExpr (obj, ProvidedType.Create ctxt ty)) + Some (ProvidedConstantExpr (obj, ProvidedType.CreateNonNull ctxt ty)) | Patterns.Coerce(arg, ty) -> - Some (ProvidedTypeAsExpr (ProvidedExpr.Create ctxt arg, ProvidedType.Create ctxt ty)) + Some (ProvidedTypeAsExpr (ProvidedExpr.CreateNonNull ctxt arg, ProvidedType.CreateNonNull ctxt ty)) | Patterns.NewTuple args -> Some (ProvidedNewTupleExpr(ProvidedExpr.CreateArray ctxt (Array.ofList args))) | Patterns.TupleGet(arg, n) -> - Some (ProvidedTupleGetExpr (ProvidedExpr.Create ctxt arg, n)) + Some (ProvidedTupleGetExpr (ProvidedExpr.CreateNonNull ctxt arg, n)) | Patterns.NewArray(ty, args) -> - Some (ProvidedNewArrayExpr(ProvidedType.Create ctxt ty, ProvidedExpr.CreateArray ctxt (Array.ofList args))) + Some (ProvidedNewArrayExpr(ProvidedType.CreateNonNull ctxt ty, ProvidedExpr.CreateArray ctxt (Array.ofList args))) | Patterns.Sequential(e1, e2) -> - Some (ProvidedSequentialExpr(ProvidedExpr.Create ctxt e1, ProvidedExpr.Create ctxt e2)) + Some (ProvidedSequentialExpr(ProvidedExpr.CreateNonNull ctxt e1, ProvidedExpr.CreateNonNull ctxt e2)) | Patterns.Lambda(v, body) -> - Some (ProvidedLambdaExpr (ProvidedVar.Create ctxt v, ProvidedExpr.Create ctxt body)) + Some (ProvidedLambdaExpr (ProvidedVar.CreateNonNull ctxt v, ProvidedExpr.CreateNonNull ctxt body)) | Patterns.TryFinally(b1, b2) -> - Some (ProvidedTryFinallyExpr (ProvidedExpr.Create ctxt b1, ProvidedExpr.Create ctxt b2)) + Some (ProvidedTryFinallyExpr (ProvidedExpr.CreateNonNull ctxt b1, ProvidedExpr.CreateNonNull ctxt b2)) | Patterns.TryWith(b, v1, e1, v2, e2) -> - Some (ProvidedTryWithExpr (ProvidedExpr.Create ctxt b, ProvidedVar.Create ctxt v1, ProvidedExpr.Create ctxt e1, ProvidedVar.Create ctxt v2, ProvidedExpr.Create ctxt e2)) + Some (ProvidedTryWithExpr (ProvidedExpr.CreateNonNull ctxt b, ProvidedVar.CreateNonNull ctxt v1, ProvidedExpr.CreateNonNull ctxt e1, ProvidedVar.CreateNonNull ctxt v2, ProvidedExpr.CreateNonNull ctxt e2)) #if PROVIDED_ADDRESS_OF - | Patterns.AddressOf e -> Some (ProvidedAddressOfExpr (ProvidedExpr.Create ctxt e)) + | Patterns.AddressOf e -> Some (ProvidedAddressOfExpr (ProvidedExpr.CreateNonNull ctxt e)) #endif | Patterns.TypeTest(e, ty) -> - Some (ProvidedTypeTestExpr(ProvidedExpr.Create ctxt e, ProvidedType.Create ctxt ty)) + Some (ProvidedTypeTestExpr(ProvidedExpr.CreateNonNull ctxt e, ProvidedType.CreateNonNull ctxt ty)) | Patterns.Let(v, e, b) -> - Some (ProvidedLetExpr (ProvidedVar.Create ctxt v, ProvidedExpr.Create ctxt e, ProvidedExpr.Create ctxt b)) + Some (ProvidedLetExpr (ProvidedVar.CreateNonNull ctxt v, ProvidedExpr.CreateNonNull ctxt e, ProvidedExpr.CreateNonNull ctxt b)) | Patterns.ForIntegerRangeLoop (v, e1, e2, e3) -> - Some (ProvidedForIntegerRangeLoopExpr (ProvidedVar.Create ctxt v, ProvidedExpr.Create ctxt e1, ProvidedExpr.Create ctxt e2, ProvidedExpr.Create ctxt e3)) + Some (ProvidedForIntegerRangeLoopExpr (ProvidedVar.CreateNonNull ctxt v, ProvidedExpr.CreateNonNull ctxt e1, ProvidedExpr.CreateNonNull ctxt e2, ProvidedExpr.CreateNonNull ctxt e3)) | Patterns.VarSet(v, e) -> - Some (ProvidedVarSetExpr (ProvidedVar.Create ctxt v, ProvidedExpr.Create ctxt e)) + Some (ProvidedVarSetExpr (ProvidedVar.CreateNonNull ctxt v, ProvidedExpr.CreateNonNull ctxt e)) | Patterns.IfThenElse(g, t, e) -> - Some (ProvidedIfThenElseExpr (ProvidedExpr.Create ctxt g, ProvidedExpr.Create ctxt t, ProvidedExpr.Create ctxt e)) + Some (ProvidedIfThenElseExpr (ProvidedExpr.CreateNonNull ctxt g, ProvidedExpr.CreateNonNull ctxt t, ProvidedExpr.CreateNonNull ctxt e)) | Patterns.Var v -> - Some (ProvidedVarExpr (ProvidedVar.Create ctxt v)) + Some (ProvidedVarExpr (ProvidedVar.CreateNonNull ctxt v)) | _ -> None + static member Create ctxt t : ProvidedExpr MaybeNull = + match box t with + | Null -> null + | _ -> ProvidedExpr (t, ctxt) - static member Create ctxt t = match box t with null -> null | _ -> ProvidedExpr (t, ctxt) + static member CreateNonNull ctxt t : ProvidedExpr = + ProvidedExpr (t, ctxt) - static member CreateArray ctxt xs = match xs with null -> null | _ -> xs |> Array.map (ProvidedExpr.Create ctxt) + static member CreateArray ctxt xs : ProvidedExpr[] = + match box xs with + | Null -> [| |] + | _ -> xs |> Array.map (ProvidedExpr.CreateNonNull ctxt) override _.Equals y = match y with :? ProvidedExpr as y -> x.Equals y.Handle | _ -> false override _.GetHashCode() = x.GetHashCode() +#if NO_CHECKNULLS [] +#else +[] +#endif type ProvidedVar (x: Var, ctxt) = member _.Type = x.Type |> ProvidedType.Create ctxt member _.Name = x.Name member _.IsMutable = x.IsMutable member _.Handle = x member _.Context = ctxt - static member Create ctxt t = match box t with null -> null | _ -> ProvidedVar (t, ctxt) - static member CreateArray ctxt xs = match xs with null -> null | _ -> xs |> Array.map (ProvidedVar.Create ctxt) + + static member CreateNonNull ctxt t = + ProvidedVar (t, ctxt) + + static member CreateArray ctxt xs : ProvidedVar[] = + match box xs with + | Null -> [| |] + | _ -> xs |> Array.map (ProvidedVar.CreateNonNull ctxt) + override _.Equals y = match y with :? ProvidedVar as y -> x.Equals y.Handle | _ -> false + override _.GetHashCode() = x.GetHashCode() /// Get the provided invoker expression for a particular use of a method. let GetInvokerExpression (provider: ITypeProvider, methodBase: ProvidedMethodBase, paramExprs: ProvidedVar[]) = - provider.GetInvokerExpression(methodBase.Handle, [| for p in paramExprs -> Expr.Var p.Handle |]) |> ProvidedExpr.Create methodBase.Context + provider.GetInvokerExpression(methodBase.Handle, [| for p in paramExprs -> Quotations.Expr.Var p.Handle |]) |> ProvidedExpr.Create methodBase.Context /// Compute the Name or FullName property of a provided type, reporting appropriate errors let CheckAndComputeProvidedNameProperty(m, st: Tainted, proj, propertyString) = @@ -976,8 +1111,7 @@ let ValidateAttributesOfProvidedType (m, st: Tainted) = errorR(Error(FSComp.SR.etMustNotBeGeneric fullName, m)) if TryTypeMember(st, fullName, "IsArray", m, false, fun st->st.IsArray) |> unmarshal then errorR(Error(FSComp.SR.etMustNotBeAnArray fullName, m)) - TryTypeMemberNonNull(st, fullName, "GetInterfaces", m, [||], fun st -> st.GetInterfaces()) |> ignore - + TryTypeMemberNonNull(st, fullName, "GetInterfaces", m, [||], fun st -> st.GetInterfaces()) |> ignore /// Verify that a provided type has the expected name let ValidateExpectedName m expectedPath expectedName (st: Tainted) = @@ -985,19 +1119,23 @@ let ValidateExpectedName m expectedPath expectedName (st: Tainted) if name <> expectedName then raise (TypeProviderError(FSComp.SR.etProvidedTypeHasUnexpectedName(expectedName, name), st.TypeProviderDesignation, m)) +#if NO_CHECKNULLS let namespaceName = TryTypeMember(st, name, "Namespace", m, "", fun st -> st.Namespace) |> unmarshal +#else + let namespaceName = TryTypeMember<_, string?>(st, name, "Namespace", m, "", fun st -> st.Namespace) |> unmarshal // TODO NULLNESS: why is this explicit instantiation needed? +#endif let rec declaringTypes (st: Tainted) accu = match TryTypeMember(st, name, "DeclaringType", m, null, fun st -> st.DeclaringType) with | Tainted.Null -> accu - | dt -> declaringTypes dt (CheckAndComputeProvidedNameProperty(m, dt, (fun dt -> dt.Name), "Name") :: accu) + | Tainted.NonNull dt -> declaringTypes dt (CheckAndComputeProvidedNameProperty(m, dt, (fun dt -> dt.Name), "Name") :: accu) let path = - [| match namespaceName with - | null -> () - | _ -> yield! namespaceName.Split([|'.'|]) - yield! declaringTypes st [] |] - + [| match namespaceName with + | Null -> () + | NonNull namespaceName -> yield! namespaceName.Split([|'.'|]) + yield! declaringTypes st [] |] + if path <> expectedPath then let expectedPath = String.Join(".", expectedPath) let path = String.Join(".", path) @@ -1008,7 +1146,11 @@ let ValidateProvidedTypeAfterStaticInstantiation(m, st: Tainted, e // Do all the calling into st up front with recovery let fullName, namespaceName, usedMembers = let name = CheckAndComputeProvidedNameProperty(m, st, (fun st -> st.Name), "Name") +#if NO_CHECKNULLS let namespaceName = TryTypeMember(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal +#else + let namespaceName = TryTypeMember<_, string?>(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal +#endif let fullName = TryTypeMemberNonNull(st, name, "FullName", m, FSComp.SR.invalidFullNameForProvidedType(), fun st -> st.FullName) |> unmarshal ValidateExpectedName m expectedPath expectedName st // Must be able to call (GetMethods|GetEvents|GetProperties|GetNestedTypes|GetConstructors)(bindingFlags). @@ -1033,19 +1175,18 @@ let ValidateProvidedTypeAfterStaticInstantiation(m, st: Tainted, e for mi in usedMembers do match mi with | Tainted.Null -> errorR(Error(FSComp.SR.etNullMember fullName, m)) - | _ -> + | Tainted.NonNull _ -> let memberName = TryMemberMember(mi, fullName, "Name", "Name", m, "invalid provided type member name", fun mi -> mi.Name) |> unmarshal if String.IsNullOrEmpty memberName then errorR(Error(FSComp.SR.etNullOrEmptyMemberName fullName, m)) else let miDeclaringType = TryMemberMember(mi, fullName, memberName, "DeclaringType", m, ProvidedType.CreateNoContext(typeof), fun mi -> mi.DeclaringType) - match miDeclaringType with // Generated nested types may have null DeclaringType | Tainted.Null when mi.OfType().IsSome -> () | Tainted.Null -> errorR(Error(FSComp.SR.etNullMemberDeclaringType(fullName, memberName), m)) - | _ -> + | Tainted.NonNull miDeclaringType -> let miDeclaringTypeFullName = TryMemberMember (miDeclaringType, fullName, memberName, "FullName", m, "invalid declaring type full name", @@ -1062,11 +1203,9 @@ let ValidateProvidedTypeAfterStaticInstantiation(m, st: Tainted, e if not isPublic || isGenericMethod then errorR(Error(FSComp.SR.etMethodHasRequirements(fullName, memberName), m)) | None -> - match mi.OfType() with | Some subType -> ValidateAttributesOfProvidedType(m, subType) | None -> - match mi.OfType() with | Some pi -> // Property must have a getter or setter @@ -1091,8 +1230,8 @@ let ValidateProvidedTypeAfterStaticInstantiation(m, st: Tainted, e | true, false -> errorR(Error(FSComp.SR.etPropertyHasSetterButNoCanWrite(memberName, fullName), m)) if not canRead && not canWrite then errorR(Error(FSComp.SR.etPropertyNeedsCanWriteOrCanRead(memberName, fullName), m)) - | None -> + | None -> match mi.OfType() with | Some ei -> // Event must have adder and remover @@ -1104,11 +1243,9 @@ let ValidateProvidedTypeAfterStaticInstantiation(m, st: Tainted, e | _, Tainted.Null -> errorR(Error(FSComp.SR.etEventNoRemove(memberName, fullName), m)) | _, _ -> () | None -> - match mi.OfType() with | Some _ -> () // TODO: Constructors must be public etc. | None -> - match mi.OfType() with | Some _ -> () // TODO: Fields must be public, literals must have a value etc. | None -> @@ -1118,7 +1255,11 @@ let ValidateProvidedTypeDefinition(m, st: Tainted, expectedPath: s // Validate the Name, Namespace and FullName properties let name = CheckAndComputeProvidedNameProperty(m, st, (fun st -> st.Name), "Name") +#if NO_CHECKNULLS let _namespaceName = TryTypeMember(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal +#else + let _namespaceName = TryTypeMember<_, (string?)>(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal +#endif let _fullname = TryTypeMemberNonNull(st, name, "FullName", m, FSComp.SR.invalidFullNameForProvidedType(), fun st -> st.FullName) |> unmarshal ValidateExpectedName m expectedPath expectedName st @@ -1129,15 +1270,15 @@ let ValidateProvidedTypeDefinition(m, st: Tainted, expectedPath: s | -1 -> () | n -> errorR(Error(FSComp.SR.etIllegalCharactersInTypeName(string expectedName[n], expectedName), m)) - let staticParameters = st.PApplyWithProvider((fun (st, provider) -> st.GetStaticParameters provider), range=m) - if staticParameters.PUntaint((fun a -> a.Length), m) = 0 then + let staticParameters : Tainted = st.PApplyWithProvider((fun (st, provider) -> st.GetStaticParameters provider), range=m) + if staticParameters.PUntaint((fun a -> (nonNull a).Length), m) = 0 then ValidateProvidedTypeAfterStaticInstantiation(m, st, expectedPath, expectedName) /// Resolve a (non-nested) provided type given a full namespace name and a type name. /// May throw an exception which will be turned into an error message by one of the 'Try' function below. /// If resolution is successful the type is then validated. -let ResolveProvidedType (resolver: Tainted, m, moduleOrNamespace: string[], typeName) = +let ResolveProvidedType (resolver: Tainted, m, moduleOrNamespace: string[], typeName) : Tainted = let displayName = String.Join(".", moduleOrNamespace) // Try to find the type in the given provided namespace @@ -1167,7 +1308,7 @@ let ResolveProvidedType (resolver: Tainted, m, moduleOrNamespace: match tryNamespaces providedNamespaces with | None -> resolver.PApply((fun _ -> null), m) | Some res -> res - + /// Try to resolve a type against the given host with the given resolution environment. let TryResolveProvidedType(resolver: Tainted, m, moduleOrNamespace, typeName) = try @@ -1184,14 +1325,14 @@ let ILPathToProvidedType (st: Tainted, m) = match st.PApply((fun st -> st.DeclaringType), m) with | Tainted.Null -> match st.PUntaint((fun st -> st.Namespace), m) with - | Null -> typeName + | Null -> typeName | NonNull ns -> ns + "." + typeName | _ -> typeName let rec encContrib (st: Tainted) = match st.PApply((fun st ->st.DeclaringType), m) with | Tainted.Null -> [] - | enc -> encContrib enc @ [ nameContrib enc ] + | Tainted.NonNull enc -> encContrib enc @ [ nameContrib enc ] encContrib st, nameContrib st @@ -1212,7 +1353,6 @@ let TryApplyProvidedMethod(methBeforeArgs: Tainted, staticAr let staticParams = methBeforeArgs.PApplyWithProvider((fun (mb, resolver) -> mb.GetStaticParametersForMethod resolver), range=m) let mangledName = ComputeMangledNameForApplyStaticParameters(nm, staticArgs, staticParams, m) mangledName - match methBeforeArgs.PApplyWithProvider((fun (mb, provider) -> mb.ApplyStaticArgumentsForMethod(provider, mangledName, staticArgs)), range=m) with | Tainted.Null -> None | Tainted.NonNull methWithArguments -> @@ -1227,7 +1367,7 @@ let TryApplyProvidedType(typeBeforeArguments: Tainted, optGenerate if staticArgs.Length = 0 then Some (typeBeforeArguments, (fun () -> ())) else - + let fullTypePathAfterArguments = // If there is a generated type name, then use that match optGeneratedTypePath with @@ -1236,10 +1376,10 @@ let TryApplyProvidedType(typeBeforeArguments: Tainted, optGenerate // Otherwise, use the full path of the erased type, including mangled arguments let nm = typeBeforeArguments.PUntaint((fun x -> x.Name), m) let enc, _ = ILPathToProvidedType (typeBeforeArguments, m) - let staticParams = typeBeforeArguments.PApplyWithProvider((fun (mb, resolver) -> mb.GetStaticParameters resolver), range=m) + let staticParams : Tainted = typeBeforeArguments.PApplyWithProvider((fun (st, resolver) -> st.GetStaticParameters resolver |> nonNull), range=m) let mangledName = ComputeMangledNameForApplyStaticParameters(nm, staticArgs, staticParams, m) enc @ [ mangledName ] - + match typeBeforeArguments.PApplyWithProvider((fun (typeBeforeArguments, provider) -> typeBeforeArguments.ApplyStaticArguments(provider, Array.ofList fullTypePathAfterArguments, staticArgs)), range=m) with | Tainted.Null -> None | Tainted.NonNull typeWithArguments -> @@ -1253,7 +1393,7 @@ let TryApplyProvidedType(typeBeforeArguments: Tainted, optGenerate /// Given a mangled name reference to a non-nested provided type, resolve it. /// If necessary, demangle its static arguments before applying them. let TryLinkProvidedType(resolver: Tainted, moduleOrNamespace: string[], typeLogicalName: string, range: range) = - + // Demangle the static parameters let typeName, argNamesAndValues = try @@ -1266,7 +1406,7 @@ let TryLinkProvidedType(resolver: Tainted, moduleOrNamespace: str match typeBeforeArguments with | Tainted.Null -> None - | _ -> + | Tainted.NonNull typeBeforeArguments -> // Take the static arguments (as strings, taken from the text in the reference we're relinking), // and convert them to objects of the appropriate type, based on the expected kind. let staticParameters = @@ -1274,7 +1414,7 @@ let TryLinkProvidedType(resolver: Tainted, moduleOrNamespace: str typeBeforeArguments.GetStaticParameters resolver),range=range0) let staticParameters = staticParameters.PApplyArray(id, "", range) - + let staticArgs = staticParameters |> Array.map (fun sp -> let typeBeforeArgumentsName = typeBeforeArguments.PUntaint ((fun st -> st.Name), range) @@ -1312,7 +1452,7 @@ let TryLinkProvidedType(resolver: Tainted, moduleOrNamespace: str | NonNull v -> v else error(Error(FSComp.SR.etProvidedTypeReferenceMissingArgument spName, range0))) - + match TryApplyProvidedType(typeBeforeArguments, None, staticArgs, range0) with | Some (typeWithArguments, checkTypeName) -> @@ -1321,7 +1461,7 @@ let TryLinkProvidedType(resolver: Tainted, moduleOrNamespace: str | None -> None /// Get the parts of a .NET namespace. Special rules: null means global, empty is not allowed. -let GetPartsOfNamespaceRecover(namespaceName: string) = +let GetPartsOfNamespaceRecover(namespaceName: string MaybeNull) = match namespaceName with | Null -> [] | NonNull namespaceName -> @@ -1329,7 +1469,7 @@ let GetPartsOfNamespaceRecover(namespaceName: string) = else splitNamespace (nonNull namespaceName) /// Get the parts of a .NET namespace. Special rules: null means global, empty is not allowed. -let GetProvidedNamespaceAsPath (m, resolver: Tainted, namespaceName: string) = +let GetProvidedNamespaceAsPath (m, resolver: Tainted, namespaceName:string MaybeNull) = match namespaceName with | Null -> [] | NonNull namespaceName -> @@ -1342,7 +1482,7 @@ let GetFSharpPathToProvidedType (st: Tainted, range) = // Can't use st.Fullname because it may be like IEnumerable // We want [System;Collections;Generic] let namespaceParts = GetPartsOfNamespaceRecover(st.PUntaint((fun st -> st.Namespace), range)) - let rec walkUpNestedClasses(st: Tainted, soFar) = + let rec walkUpNestedClasses(st: Tainted, soFar) = match st with | Tainted.Null -> soFar | Tainted.NonNull st -> walkUpNestedClasses(st.PApply((fun st ->st.DeclaringType), range), soFar) @ [st.PUntaint((fun st -> st.Name), range)] @@ -1359,8 +1499,8 @@ let GetOriginalILAssemblyRefOfProvidedAssembly (assembly: Tainted, range) = - - let aref = GetOriginalILAssemblyRefOfProvidedAssembly (st.PApply((fun st -> st.Assembly), range), range) + + let aref = GetOriginalILAssemblyRefOfProvidedAssembly (st.PApply((fun st -> nonNull st.Assembly), range), range) // NULLNESS TODO: why is explicit instantiation needed here let scoperef = ILScopeRef.Assembly aref let enc, nm = ILPathToProvidedType (st, range) let tref = ILTypeRef.Create(scoperef, enc, nm) @@ -1379,7 +1519,6 @@ type ProviderGeneratedType = ProviderGeneratedType of ilOrigTyRef: ILTypeRef * i /// names in the statically linked, embedded assembly, plus what types are nested in side what types. type ProvidedAssemblyStaticLinkingMap = { ILTypeMap: Dictionary } - static member CreateNew() = { ILTypeMap = Dictionary() } diff --git a/src/Compiler/TypedTree/TypeProviders.fsi b/src/Compiler/TypedTree/TypeProviders.fsi index b1e3ccaf85c..6b264a118e7 100755 --- a/src/Compiler/TypedTree/TypeProviders.fsi +++ b/src/Compiler/TypedTree/TypeProviders.fsi @@ -9,6 +9,7 @@ module internal rec FSharp.Compiler.TypeProviders open System open System.Collections.Concurrent open System.Collections.Generic +open Internal.Utilities.Library open FSharp.Core.CompilerServices open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.Text @@ -90,7 +91,10 @@ type ProvidedTypeContext = /// Map the TyconRef objects, if any member RemapTyconRefs: (obj -> obj) -> ProvidedTypeContext -[] +[] +#if NO_CHECKNULLS +[] +#endif type ProvidedType = inherit ProvidedMemberInfo @@ -110,7 +114,7 @@ type ProvidedType = member Assembly: ProvidedAssembly - member BaseType: ProvidedType + member BaseType: ProvidedType MaybeNull member GetNestedType: string -> ProvidedType @@ -204,9 +208,10 @@ type ProvidedType = static member TaintedEquals: Tainted * Tainted -> bool +#if NO_CHECKNULLS [] +#endif type IProvidedCustomAttributeProvider = - abstract GetHasTypeProviderEditorHideMethodsAttribute: provider: ITypeProvider -> bool abstract GetDefinitionLocationAttribute: provider: ITypeProvider -> (string * int * int) option @@ -215,10 +220,12 @@ type IProvidedCustomAttributeProvider = abstract GetAttributeConstructorArgs: provider: ITypeProvider * attribName: string -> (obj option list * (string * obj option) list) option - -[] -type ProvidedAssembly = - + +[] +#if NO_CHECKNULLS +[] +#endif +type ProvidedAssembly = member GetName: unit -> System.Reflection.AssemblyName member FullName: string @@ -227,18 +234,23 @@ type ProvidedAssembly = member Handle: System.Reflection.Assembly -[] -type ProvidedMemberInfo = +[] +#if NO_CHECKNULLS +[] +#endif +type ProvidedMemberInfo = member Name: string - member DeclaringType: ProvidedType - - interface IProvidedCustomAttributeProvider + member DeclaringType: ProvidedType MaybeNull -[] -type ProvidedMethodBase = + interface IProvidedCustomAttributeProvider +[] +#if NO_CHECKNULLS +[] +#endif +type ProvidedMethodBase = inherit ProvidedMemberInfo member IsGenericMethod: bool @@ -273,8 +285,11 @@ type ProvidedMethodBase = static member TaintedEquals: Tainted * Tainted -> bool -[] -type ProvidedMethodInfo = +[] +#if NO_CHECKNULLS +[] +#endif +type ProvidedMethodInfo = inherit ProvidedMethodBase @@ -282,8 +297,11 @@ type ProvidedMethodInfo = member MetadataToken: int -[] -type ProvidedParameterInfo = +[] +#if NO_CHECKNULLS +[] +#endif +type ProvidedParameterInfo = member Name: string @@ -301,8 +319,11 @@ type ProvidedParameterInfo = interface IProvidedCustomAttributeProvider -[] -type ProvidedFieldInfo = +[] +#if NO_CHECKNULLS +[] +#endif +type ProvidedFieldInfo = inherit ProvidedMemberInfo @@ -330,8 +351,11 @@ type ProvidedFieldInfo = static member TaintedEquals: Tainted * Tainted -> bool -[] -type ProvidedPropertyInfo = +[] +#if NO_CHECKNULLS +[] +#endif +type ProvidedPropertyInfo = inherit ProvidedMemberInfo @@ -351,8 +375,11 @@ type ProvidedPropertyInfo = static member TaintedEquals: Tainted * Tainted -> bool -[] -type ProvidedEventInfo = +[] +#if NO_CHECKNULLS +[] +#endif +type ProvidedEventInfo = inherit ProvidedMemberInfo @@ -366,8 +393,11 @@ type ProvidedEventInfo = static member TaintedEquals: Tainted * Tainted -> bool -[] -type ProvidedConstructorInfo = +[] +#if NO_CHECKNULLS +[] +#endif +type ProvidedConstructorInfo = inherit ProvidedMethodBase type ProvidedExprType = @@ -415,8 +445,11 @@ type ProvidedExprType = | ProvidedIfThenElseExpr of ProvidedExpr * ProvidedExpr * ProvidedExpr | ProvidedVarExpr of ProvidedVar - -[] + +[] +#if NO_CHECKNULLS +[] +#endif type ProvidedExpr = member Type: ProvidedType @@ -426,7 +459,10 @@ type ProvidedExpr = member GetExprType: unit -> ProvidedExprType option -[] +[] +#if NO_CHECKNULLS +[] +#endif type ProvidedVar = member Type: ProvidedType diff --git a/src/Compiler/TypedTree/TypedTree.fs b/src/Compiler/TypedTree/TypedTree.fs index b18cdd1d2a9..8213e884d4b 100644 --- a/src/Compiler/TypedTree/TypedTree.fs +++ b/src/Compiler/TypedTree/TypedTree.fs @@ -2305,14 +2305,18 @@ type Typar = | None -> () /// Links a previously unlinked type variable to the given data. Only used during unpickling of F# metadata. - member x.AsType = - let ty = x.typar_astype - match box ty with - | null -> - let ty2 = TType_var (x, 0uy) - x.typar_astype <- ty2 - ty2 - | _ -> ty + member x.AsType nullness = + match nullness with + | Nullness.Known NullnessInfo.AmbivalentToNull -> + let ty = x.typar_astype + match box ty with + | null -> + let ty2 = TType_var (x, Nullness.Known NullnessInfo.AmbivalentToNull) + x.typar_astype <- ty2 + ty2 + | _ -> ty + | _ -> + TType_var (x, nullness) /// Indicates if a type variable has been linked. Only used during unpickling of F# metadata. member x.IsLinked = x.typar_stamp <> -1L @@ -2373,6 +2377,9 @@ type TyparConstraint = /// A constraint that a type has a 'null' value | SupportsNull of range: range + /// A constraint that a type doesn't support nullness + | NotSupportsNull of range + /// A constraint that a type has a member with the given signature | MayResolveMember of constraintInfo: TraitConstraintInfo * range: range @@ -4174,6 +4181,63 @@ type RecdFieldRef = override x.ToString() = x.FieldName +[] +type Nullness = + | Known of NullnessInfo + | Variable of NullnessVar + + member n.Evaluate() = + match n with + | Known info -> info + | Variable v -> v.Evaluate() + + member n.TryEvaluate() = + match n with + | Known info -> ValueSome info + | Variable v -> v.TryEvaluate() + + override n.ToString() = match n.Evaluate() with NullnessInfo.WithNull -> "?" | NullnessInfo.WithoutNull -> "" | NullnessInfo.AmbivalentToNull -> "%" + +// Note, nullness variables are only created if the nullness checking feature is on +type NullnessVar() = + let mutable solution: Nullness option = None + + member nv.Evaluate() = + match solution with + | None -> NullnessInfo.WithoutNull + | Some soln -> soln.Evaluate() + + member nv.TryEvaluate() = + match solution with + | None -> ValueNone + | Some soln -> soln.TryEvaluate() + + member nv.IsSolved = solution.IsSome + + member nv.Set(nullness) = + assert (not nv.IsSolved) + solution <- Some nullness + + member nv.Unset() = + assert nv.IsSolved + solution <- None + + member nv.Solution = + assert nv.IsSolved + solution.Value + +[] +type NullnessInfo = + + /// we know that there is an extra null value in the type + | WithNull + + /// we know that there is no extra null value in the type + | WithoutNull + + /// we know we don't care + | AmbivalentToNull + /// Represents a type in the typed abstract syntax [] type TType = @@ -4181,10 +4245,10 @@ type TType = /// Indicates the type is a universal type, only used for types of values and members | TType_forall of typars: Typars * bodyTy: TType - /// Indicates the type is built from a named type and a number of type arguments. + /// TType_app(tyconRef, typeInstantiation, nullness). /// - /// 'flags' is a placeholder for future features, in particular nullness analysis - | TType_app of tyconRef: TyconRef * typeInstantiation: TypeInst * flags: byte + /// Indicates the type is built from a named type and a number of type arguments + | TType_app of tyconRef: TyconRef * typeInstantiation: TypeInst * nullness: Nullness /// Indicates the type is an anonymous record type whose compiled representation is located in the given assembly | TType_anon of anonInfo: AnonRecdTypeInfo * tys: TType list @@ -4192,10 +4256,10 @@ type TType = /// Indicates the type is a tuple type. elementTypes must be of length 2 or greater. | TType_tuple of tupInfo: TupInfo * elementTypes: TTypes - /// Indicates the type is a function type. + /// TType_fun(domainType, rangeType, nullness). /// - /// 'flags' is a placeholder for future features, in particular nullness analysis. - | TType_fun of domainType: TType * rangeType: TType * flags: byte + /// Indicates the type is a function type + | TType_fun of domainType: TType * rangeType: TType * nullness: Nullness /// Indicates the type is a non-F#-visible type representing a "proof" that a union value belongs to a particular union case /// These types are not user-visible and will never appear as an inferred type. They are the types given to @@ -4203,9 +4267,7 @@ type TType = | TType_ucase of unionCaseRef: UnionCaseRef * typeInstantiation: TypeInst /// Indicates the type is a variable type, whether declared, generalized or an inference type parameter - /// - /// 'flags' is a placeholder for future features, in particular nullness analysis - | TType_var of typar: Typar * flags: byte + | TType_var of typar: Typar * nullness: Nullness /// Indicates the type is a unit-of-measure expression being used as an argument to a type or member | TType_measure of measure: Measure @@ -4231,18 +4293,18 @@ type TType = override x.ToString() = match x with | TType_forall (_tps, ty) -> "forall ... " + ty.ToString() - | TType_app (tcref, tinst, _) -> tcref.DisplayName + (match tinst with [] -> "" | tys -> "<" + String.concat "," (List.map string tys) + ">") + | TType_app (tcref, tinst, nullness) -> tcref.DisplayName + (match tinst with [] -> "" | tys -> "<" + String.concat "," (List.map string tys) + ">") + nullness.ToString() | TType_tuple (tupInfo, tinst) -> (match tupInfo with | TupInfo.Const false -> "" | TupInfo.Const true -> "struct ") - + String.concat "," (List.map string tinst) + + String.concat "," (List.map string tinst) + ")" | TType_anon (anonInfo, tinst) -> (match anonInfo.TupInfo with | TupInfo.Const false -> "" | TupInfo.Const true -> "struct ") + "{|" + String.concat "," (Seq.map2 (fun nm ty -> nm + " " + string ty + ";") anonInfo.SortedNames tinst) + "|}" - | TType_fun (domainTy, retTy, _) -> "(" + string domainTy + " -> " + string retTy + ")" + | TType_fun (domainTy, retTy, nullness) -> "(" + string domainTy + " -> " + string retTy + ")" + nullness.ToString() | TType_ucase (uc, tinst) -> "ucase " + uc.CaseName + (match tinst with [] -> "" | tys -> "<" + String.concat "," (List.map string tys) + ">") | TType_var (tp, _) -> match tp.Solution with @@ -4304,7 +4366,7 @@ type AnonRecdTypeInfo = x.Stamp <- d.Stamp x.SortedNames <- sortedNames - member x.IsLinked = (match x.SortedIds with null -> true | _ -> false) + member x.IsLinked = (match box x.SortedIds with null -> true | _ -> false) member x.DisplayNameCoreByIdx idx = x.SortedNames[idx] @@ -5512,12 +5574,12 @@ type CcuThunk = /// Dereference the assembly reference member ccu.Deref = - if isNull (ccu.target :> obj) then + if isNull (box ccu.target) then raise(UnresolvedReferenceNoRange ccu.name) ccu.target /// Indicates if this assembly reference is unresolved - member ccu.IsUnresolvedReference = isNull (ccu.target :> obj) + member ccu.IsUnresolvedReference = isNull (box ccu.target) /// Ensure the ccu is derefable in advance. Supply a path to attach to any resulting error message. member ccu.EnsureDerefable(requiringPath: string[]) = @@ -5772,7 +5834,7 @@ type Construct() = let lazyBaseTy = LazyWithContext.Create ((fun (m, objTy) -> - let baseSystemTy = st.PApplyOption((fun st -> match st.BaseType with null -> None | ty -> Some ty), m) + let baseSystemTy = st.PApplyOption((fun st -> match st.BaseType with null -> None | ty -> Some (nonNull ty)), m) match baseSystemTy with | None -> objTy | Some t -> importProvidedType t), @@ -5786,7 +5848,9 @@ type Construct() = IsDelegate = (fun () -> st.PUntaint((fun st -> let baseType = st.BaseType match baseType with - | null -> false + | Null -> false + | NonNull x -> + match x with | x when x.IsGenericType -> false | x when x.DeclaringType <> null -> false | x -> x.FullName = "System.Delegate" || x.FullName = "System.MulticastDelegate"), m)) @@ -6080,8 +6144,8 @@ type Construct() = static member ComputeDefinitionLocationOfProvidedItem<'T when 'T :> IProvidedCustomAttributeProvider> (p: Tainted<'T>) : range option = let attrs = p.PUntaintNoFailure(fun x -> x.GetDefinitionLocationAttribute(p.TypeProvider.PUntaintNoFailure id)) match attrs with - | None | Some (null, _, _) -> None - | Some (filePath, line, column) -> + | None | Some (Null, _, _) -> None + | Some (NonNull filePath, line, column) -> // Coordinates from type provider are 1-based for lines and columns // Coordinates internally in the F# compiler are 1-based for lines and 0-based for columns let pos = Position.mkPos line (max 0 (column - 1)) diff --git a/src/Compiler/TypedTree/TypedTree.fsi b/src/Compiler/TypedTree/TypedTree.fsi index bcc951ecc4d..e6724a16fb4 100644 --- a/src/Compiler/TypedTree/TypedTree.fsi +++ b/src/Compiler/TypedTree/TypedTree.fsi @@ -1530,7 +1530,7 @@ type Typar = override ToString: unit -> string /// Links a previously unlinked type variable to the given data. Only used during unpickling of F# metadata. - member AsType: TType + member AsType: nullness: Nullness -> TType /// The declared attributes of the type parameter. Empty for type inference variables type parameters from .NET. member Attribs: Attribs @@ -1615,6 +1615,9 @@ type TyparConstraint = /// A constraint that a type has a 'null' value | SupportsNull of range: range + /// A constraint that a type doesn't support nullness + | NotSupportsNull of range + /// A constraint that a type has a member with the given signature | MayResolveMember of constraintInfo: TraitConstraintInfo * range: range @@ -3008,6 +3011,36 @@ type RecdFieldRef = /// Get a reference to the type containing this union case member TyconRef: TyconRef +[] +type NullnessInfo = + + /// we know that there is an extra null value in the type + | WithNull + + /// we know that there is no extra null value in the type + | WithoutNull + + /// we know we don't care + | AmbivalentToNull + +[] +type Nullness = + | Known of NullnessInfo + | Variable of NullnessVar + + member Evaluate: unit -> NullnessInfo + + member TryEvaluate: unit -> NullnessInfo voption + +type NullnessVar = + new: unit -> NullnessVar + member Evaluate: unit -> NullnessInfo + member TryEvaluate: unit -> NullnessInfo voption + member IsSolved: bool + member Set: Nullness -> unit + member Unset: unit -> unit + member Solution: Nullness + /// Represents a type in the typed abstract syntax [] type TType = @@ -3018,7 +3051,7 @@ type TType = /// Indicates the type is built from a named type type a number of type arguments. /// /// 'flags' is a placeholder for future features, in particular nullness analysis - | TType_app of tyconRef: TyconRef * typeInstantiation: TypeInst * flags: byte + | TType_app of tyconRef: TyconRef * typeInstantiation: TypeInst * nullness: Nullness /// Indicates the type is an anonymous record type whose compiled representation is located in the given assembly | TType_anon of anonInfo: AnonRecdTypeInfo * tys: TType list @@ -3029,7 +3062,7 @@ type TType = /// Indicates the type is a function type. /// /// 'flags' is a placeholder for future features, in particular nullness analysis. - | TType_fun of domainType: TType * rangeType: TType * flags: byte + | TType_fun of domainType: TType * rangeType: TType * nullness: Nullness /// Indicates the type is a non-F#-visible type representing a "proof" that a union value belongs to a particular union case /// These types are not user-visible type will never appear as an inferred type. They are the types given to @@ -3039,7 +3072,7 @@ type TType = /// Indicates the type is a variable type, whether declared, generalized or an inference type parameter /// /// 'flags' is a placeholder for future features, in particular nullness analysis - | TType_var of typar: Typar * flags: byte + | TType_var of typar: Typar * nullness: Nullness /// Indicates the type is a unit-of-measure expression being used as an argument to a type or member | TType_measure of measure: Measure diff --git a/src/Compiler/TypedTree/TypedTreeBasics.fs b/src/Compiler/TypedTree/TypedTreeBasics.fs index 651eadd0d65..04052291cb1 100644 --- a/src/Compiler/TypedTree/TypedTreeBasics.fs +++ b/src/Compiler/TypedTree/TypedTreeBasics.fs @@ -189,9 +189,17 @@ let ccuOfTyconRef eref = // Type parameters and inference unknowns //------------------------------------------------------------------------- -let mkTyparTy (tp: Typar) = +let NewNullnessVar() = Nullness.Variable (NullnessVar()) // we don't known (and if we never find out then it's non-null) + +let KnownAmbivalentToNull = Nullness.Known NullnessInfo.AmbivalentToNull + +let KnownWithNull = Nullness.Known NullnessInfo.WithNull + +let KnownWithoutNull = Nullness.Known NullnessInfo.WithoutNull + +let mkTyparTy (tp:Typar) = match tp.Kind with - | TyparKind.Type -> tp.AsType + | TyparKind.Type -> tp.AsType KnownWithoutNull // TODO NULLNESS: check various callers | TyparKind.Measure -> TType_measure (Measure.Var tp) // For fresh type variables clear the StaticReq when copying because the requirement will be re-established through the @@ -234,9 +242,49 @@ let rec stripUnitEqnsAux canShortcut unt = | Measure.Var r when r.IsSolved -> stripUnitEqnsAux canShortcut (tryShortcutSolvedUnitPar canShortcut r) | _ -> unt -let rec stripTyparEqnsAux canShortcut ty = +let combineNullness (nullnessOrig: Nullness) (nullnessNew: Nullness) = + match nullnessOrig.Evaluate() with + | NullnessInfo.WithoutNull -> nullnessNew + | NullnessInfo.AmbivalentToNull -> nullnessOrig + | NullnessInfo.WithNull -> + match nullnessNew.Evaluate() with + | NullnessInfo.WithoutNull -> nullnessOrig + | NullnessInfo.AmbivalentToNull -> nullnessNew + | NullnessInfo.WithNull -> nullnessOrig + +let tryAddNullnessToTy nullnessNew (ty:TType) = + match ty with + | TType_var (tp, nullnessOrig) -> + // TODO NULLNESS: make this avoid allocation if no change + Some (TType_var (tp, combineNullness nullnessOrig nullnessNew)) + | TType_app (tcr, tinst, nullnessOrig) -> + // TODO NULLNESS: make this avoid allocation if no change + Some (TType_app (tcr, tinst, combineNullness nullnessOrig nullnessNew)) + | TType_ucase _ -> None // TODO NULLNESS + | TType_tuple _ -> None // TODO NULLNESS + | TType_anon _ -> None // TODO NULLNESS + | TType_fun (d, r, nullnessOrig) -> + // TODO NULLNESS: make this avoid allocation if no change + Some (TType_fun (d, r, combineNullness nullnessOrig nullnessNew)) + | TType_forall _ -> None + | TType_measure _ -> None + +let addNullnessToTy (nullness: Nullness) (ty:TType) = + match nullness.Evaluate() with + | NullnessInfo.WithoutNull -> ty + | _ -> + match ty with + | TType_var (tp, nullnessOrig) -> TType_var (tp, combineNullness nullnessOrig nullness) + | TType_app (tcr, tinst, nullnessOrig) -> TType_app (tcr, tinst, combineNullness nullnessOrig nullness) + | TType_fun (d, r, nullnessOrig) -> TType_fun (d, r, combineNullness nullnessOrig nullness) + //| TType_ucase _ -> None // TODO NULLNESS + //| TType_tuple _ -> None // TODO NULLNESS + //| TType_anon _ -> None // TODO NULLNESS + | _ -> ty + +let rec stripTyparEqnsAux nullness0 canShortcut ty = match ty with - | TType_var (r, _) -> + | TType_var (r, nullness) -> match r.Solution with | Some soln -> if canShortcut then @@ -245,23 +293,36 @@ let rec stripTyparEqnsAux canShortcut ty = // This is only because IterType likes to walk _all_ the constraints _everywhere_ in a type, including // those attached to _solved_ type variables. In an ideal world this would never be needed - see the notes // on IterType. - | TType_var (r2, _) when r2.Constraints.IsEmpty -> - match r2.Solution with - | None -> () - | Some _ as soln2 -> - r.typar_solution <- soln2 + | TType_var (r2, nullness2) when r2.Constraints.IsEmpty -> + match nullness2.Evaluate() with + | NullnessInfo.WithoutNull -> + match r2.Solution with + | None -> () + | Some _ as soln2 -> + r.typar_solution <- soln2 + | _ -> () | _ -> () - stripTyparEqnsAux canShortcut soln + stripTyparEqnsAux (combineNullness nullness0 nullness) canShortcut soln | None -> - ty + addNullnessToTy nullness0 ty | TType_measure unt -> TType_measure (stripUnitEqnsAux canShortcut unt) | _ -> ty -let stripTyparEqns ty = stripTyparEqnsAux false ty +let stripTyparEqns ty = stripTyparEqnsAux KnownWithoutNull false ty let stripUnitEqns unt = stripUnitEqnsAux false unt +let replaceNullnessOfTy nullness (ty:TType) = + match stripTyparEqns ty with + | TType_var (tp, _) -> TType_var (tp, nullness) + | TType_app (tcr, tinst, _) -> TType_app (tcr, tinst, nullness) + | TType_fun (d, r, _) -> TType_fun (d, r, nullness) + //| TType_ucase _ -> None // TODO NULLNESS + //| TType_tuple _ -> None // TODO NULLNESS + //| TType_anon _ -> None // TODO NULLNESS + | sty -> sty + /// Detect a use of a nominal type, including type abbreviations. let (|AbbrevOrAppTy|_|) (ty: TType) = match stripTyparEqns ty with diff --git a/src/Compiler/TypedTree/TypedTreeBasics.fsi b/src/Compiler/TypedTree/TypedTreeBasics.fsi index 8a73a609316..7770c392f78 100644 --- a/src/Compiler/TypedTree/TypedTreeBasics.fsi +++ b/src/Compiler/TypedTree/TypedTreeBasics.fsi @@ -120,6 +120,20 @@ val ccuOfValRef: vref: ValRef -> CcuThunk option val ccuOfTyconRef: eref: EntityRef -> CcuThunk option +val NewNullnessVar: unit -> Nullness + +val KnownAmbivalentToNull: Nullness + +val KnownWithNull: Nullness + +val KnownWithoutNull: Nullness + +val combineNullness: Nullness -> Nullness -> Nullness + +val tryAddNullnessToTy: Nullness -> TType -> TType option + +val addNullnessToTy: Nullness -> TType -> TType + val mkTyparTy: tp: Typar -> TType val copyTypars: clearStaticReq: bool -> tps: Typar list -> Typar list @@ -128,7 +142,9 @@ val tryShortcutSolvedUnitPar: canShortcut: bool -> r: Typar -> Measure val stripUnitEqnsAux: canShortcut: bool -> unt: Measure -> Measure -val stripTyparEqnsAux: canShortcut: bool -> ty: TType -> TType +val stripTyparEqnsAux: nullness0: Nullness -> canShortcut: bool -> ty: TType -> TType + +val replaceNullnessOfTy: nullness: Nullness -> ty: TType -> TType val stripTyparEqns: ty: TType -> TType diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs index 702f7292429..755e2e725ab 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.fs @@ -160,8 +160,9 @@ let generalizeTypars tps = List.map generalizeTypar tps let rec remapTypeAux (tyenv: Remap) (ty: TType) = let ty = stripTyparEqns ty match ty with - | TType_var (tp, _) as ty -> - instTyparRef tyenv.tpinst ty tp + | TType_var (tp, nullness) as ty -> + let res = instTyparRef tyenv.tpinst ty tp + addNullnessToTy nullness res | TType_app (tcref, tinst, flags) as ty -> match tyenv.tyconRefRemap.TryFind tcref with @@ -251,6 +252,7 @@ and remapTyparConstraintsAux tyenv cs = | TyparConstraint.SupportsComparison _ | TyparConstraint.SupportsEquality _ | TyparConstraint.SupportsNull _ + | TyparConstraint.NotSupportsNull _ | TyparConstraint.IsUnmanaged _ | TyparConstraint.IsNonNullableStruct _ | TyparConstraint.IsReferenceType _ @@ -616,12 +618,12 @@ let mkByrefTyWithInference (g: TcGlobals) ty1 ty2 = else TType_app (g.byref_tcr, [ty1], g.knownWithoutNull) -let mkArrayTy (g: TcGlobals) rank ty m = +let mkArrayTy (g: TcGlobals) rank nullness ty m = if rank < 1 || rank > 32 then errorR(Error(FSComp.SR.tastopsMaxArrayThirtyTwo rank, m)) - TType_app (g.il_arr_tcr_map[3], [ty], g.knownWithoutNull) + TType_app (g.il_arr_tcr_map[3], [ty], nullness) else - TType_app (g.il_arr_tcr_map[rank - 1], [ty], g.knownWithoutNull) + TType_app (g.il_arr_tcr_map[rank - 1], [ty], nullness) //-------------------------------------------------------------------------- // Tuple compilation (types) @@ -720,13 +722,15 @@ let reduceTyconRefMeasureableOrProvided (g: TcGlobals) (tcref: TyconRef) tyargs reduceTyconMeasureableOrProvided g tcref.Deref tyargs let rec stripTyEqnsA g canShortcut ty = - let ty = stripTyparEqnsAux canShortcut ty + let ty = stripTyparEqnsAux KnownWithoutNull canShortcut ty match ty with - | TType_app (tcref, tinst, _) -> + | TType_app (tcref, tinst, nullness) -> let tycon = tcref.Deref match tycon.TypeAbbrev with | Some abbrevTy -> - stripTyEqnsA g canShortcut (applyTyconAbbrev abbrevTy tycon tinst) + let reducedTy = applyTyconAbbrev abbrevTy tycon tinst + let reducedTy2 = addNullnessToTy nullness reducedTy + stripTyEqnsA g canShortcut reducedTy2 | None -> // This is the point where we get to add additional conditional normalizing equations // into the type system. Such power! @@ -738,7 +742,9 @@ let rec stripTyEqnsA g canShortcut ty = // Add the equation double<1> = double for units of measure. elif tycon.IsMeasureableReprTycon && List.forall (isDimensionless g) tinst then - stripTyEqnsA g canShortcut (reduceTyconMeasureableOrProvided g tycon tinst) + let reducedTy = reduceTyconMeasureableOrProvided g tycon tinst + let reducedTy2 = addNullnessToTy nullness reducedTy + stripTyEqnsA g canShortcut reducedTy2 else ty | ty -> ty @@ -759,17 +765,19 @@ let evalAnonInfoIsStruct (anonInfo: AnonRecdTypeInfo) = let rec stripTyEqnsAndErase eraseFuncAndTuple (g: TcGlobals) ty = let ty = stripTyEqns g ty match ty with - | TType_app (tcref, args, _) -> + | TType_app (tcref, args, nullness) -> let tycon = tcref.Deref - if tycon.IsErased then - stripTyEqnsAndErase eraseFuncAndTuple g (reduceTyconMeasureableOrProvided g tycon args) + if tycon.IsErased then + let reducedTy = reduceTyconMeasureableOrProvided g tycon args + let reducedTy2 = addNullnessToTy nullness reducedTy + stripTyEqnsAndErase eraseFuncAndTuple g reducedTy2 elif tyconRefEq g tcref g.nativeptr_tcr && eraseFuncAndTuple then stripTyEqnsAndErase eraseFuncAndTuple g g.nativeint_ty else ty - | TType_fun(domainTy, rangeTy, flags) when eraseFuncAndTuple -> - TType_app(g.fastFunc_tcr, [ domainTy; rangeTy ], flags) + | TType_fun(domainTy, rangeTy, nullness) when eraseFuncAndTuple -> + TType_app(g.fastFunc_tcr, [ domainTy; rangeTy ], nullness) | TType_tuple(tupInfo, l) when eraseFuncAndTuple -> mkCompiledTupleTy g (evalTupInfoIsStruct tupInfo) l @@ -843,7 +851,7 @@ let isMeasureTy g ty = ty |> stripTyEqns g |> (function TType_measure _ -> true let isProvenUnionCaseTy ty = match ty with TType_ucase _ -> true | _ -> false -let mkAppTy tcref tyargs = TType_app(tcref, tyargs, 0uy) +let mkAppTy tcref tyargs = TType_app(tcref, tyargs, KnownWithoutNull) // TODO NULLNESS - check various callers let mkProvenUnionCaseTy ucref tyargs = TType_ucase(ucref, tyargs) @@ -855,6 +863,8 @@ let destAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, tinst, _) let tcrefOfAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> tcref | _ -> failwith "tcrefOfAppTy") +let nullnessOfTy g ty = ty |> stripTyEqns g |> (function TType_app(_, _, nullness) | TType_fun (_, _, nullness) | TType_var (_, nullness) -> nullness | _ -> g.knownWithoutNull) + let argsOfAppTy g ty = ty |> stripTyEqns g |> (function TType_app(_, tinst, _) -> tinst | _ -> []) let tryDestTyparTy g ty = ty |> stripTyEqns g |> (function TType_var (v, _) -> ValueSome v | _ -> ValueNone) @@ -876,14 +886,14 @@ 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 tryNiceEntityRefOfTy ty = - let ty = stripTyparEqnsAux false ty + let ty = stripTyparEqnsAux KnownWithoutNull false ty match ty with | TType_app (tcref, _, _) -> ValueSome tcref | TType_measure (Measure.Const tcref) -> ValueSome tcref | _ -> ValueNone let tryNiceEntityRefOfTyOption ty = - let ty = stripTyparEqnsAux false ty + let ty = stripTyparEqnsAux KnownWithoutNull false ty match ty with | TType_app (tcref, _, _) -> Some tcref | TType_measure (Measure.Const tcref) -> Some tcref @@ -912,9 +922,9 @@ let convertToTypeWithMetadataIfPossible g ty = let stripMeasuresFromTy g ty = match ty with - | TType_app(tcref, tinst, flags) -> + | TType_app(tcref, tinst, nullness) -> let tinstR = tinst |> List.filter (isMeasureTy g >> not) - TType_app(tcref, tinstR, flags) + TType_app(tcref, tinstR, nullness) | _ -> ty //--------------------------------------------------------------------------- @@ -999,6 +1009,7 @@ and typarConstraintsAEquivAux erasureFlag g aenv tpc1 tpc2 = | TyparConstraint.SupportsComparison _, TyparConstraint.SupportsComparison _ | TyparConstraint.SupportsEquality _, TyparConstraint.SupportsEquality _ | TyparConstraint.SupportsNull _, TyparConstraint.SupportsNull _ + | TyparConstraint.NotSupportsNull _, TyparConstraint.NotSupportsNull _ | TyparConstraint.IsNonNullableStruct _, TyparConstraint.IsNonNullableStruct _ | TyparConstraint.IsReferenceType _, TyparConstraint.IsReferenceType _ | TyparConstraint.IsUnmanaged _, TyparConstraint.IsUnmanaged _ @@ -1025,7 +1036,7 @@ and typeAEquivAux erasureFlag g aenv ty1 ty2 = | TType_forall(tps1, rty1), TType_forall(tps2, retTy2) -> typarsAEquivAux erasureFlag g aenv tps1 tps2 && typeAEquivAux erasureFlag g (aenv.BindEquivTypars tps1 tps2) rty1 retTy2 - | TType_var (tp1, _), TType_var (tp2, _) when typarEq tp1 tp2 -> + | TType_var (tp1, _), TType_var (tp2, _) when typarEq tp1 tp2 -> // NOTE: nullness annotations are ignored for type equivalence true | TType_var (tp1, _), _ -> @@ -1033,7 +1044,8 @@ and typeAEquivAux erasureFlag g aenv ty1 ty2 = | Some tpTy1 -> typeEquivAux erasureFlag g tpTy1 ty2 | None -> false - | TType_app (tcref1, tinst1, _), TType_app (tcref2, tinst2, _) -> + // NOTE: nullness annotations are ignored for type equivalence + | TType_app (tcref1, tinst1, _), TType_app (tcref2, tinst2, _) -> tcrefAEquiv g aenv tcref1 tcref2 && typesAEquivAux erasureFlag g aenv tinst1 tinst2 @@ -1045,13 +1057,14 @@ and typeAEquivAux erasureFlag g aenv ty1 ty2 = | TType_tuple (tupInfo1, l1), TType_tuple (tupInfo2, l2) -> structnessAEquiv tupInfo1 tupInfo2 && typesAEquivAux erasureFlag g aenv l1 l2 + // NOTE: nullness annotations are ignored for type equivalence + | TType_fun (domainTy1, rangeTy1, _), TType_fun (domainTy2, rangeTy2, _) -> + typeAEquivAux erasureFlag g aenv domainTy1 domainTy2 && typeAEquivAux erasureFlag g aenv rangeTy1 rangeTy2 + | TType_anon (anonInfo1, l1), TType_anon (anonInfo2, l2) -> anonInfoEquiv anonInfo1 anonInfo2 && typesAEquivAux erasureFlag g aenv l1 l2 - | TType_fun (domainTy1, rangeTy1, _), TType_fun (domainTy2, rangeTy2, _) -> - typeAEquivAux erasureFlag g aenv domainTy1 domainTy2 && typeAEquivAux erasureFlag g aenv rangeTy1 rangeTy2 - | TType_measure m1, TType_measure m2 -> match erasureFlag with | EraseNone -> measureAEquiv g aenv m1 m2 @@ -1124,12 +1137,24 @@ 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_var (tp, nullness) -> + match nullness.Evaluate() with + | NullnessInfo.WithNull -> [ty] // with-null annotations can't be tested at runtime (TODO NULLNESS: for value types Nullable<_> they can be) + | _ -> if tp.IsErased then [ty] else [] + + | TType_app (_, b, nullness) -> + match nullness.Evaluate() with + | NullnessInfo.WithNull -> [ty] + | _ -> List.foldBack (fun ty tys -> getErasedTypes g ty @ tys) b [] + + | TType_ucase(_, b) | TType_anon (_, b) | TType_tuple (_, b) -> List.foldBack (fun ty tys -> getErasedTypes g ty @ tys) b [] - | TType_fun (domainTy, rangeTy, _) -> - getErasedTypes g domainTy @ getErasedTypes g rangeTy + + | TType_fun (domainTy, rangeTy, nullness) -> + match nullness.Evaluate() with + | NullnessInfo.WithNull -> [ty] + | _ -> getErasedTypes g domainTy @ getErasedTypes g rangeTy | TType_measure _ -> [ty] @@ -1808,6 +1833,7 @@ let isInByrefTy g ty = | _ -> false) let isOutByrefTag g ty = ty |> stripTyEqns g |> (function TType_app(tcref, [], _) -> tyconRefEq g g.byrefkind_Out_tcr tcref | _ -> false) + let isOutByrefTy g ty = ty |> stripTyEqns g |> (function | TType_app(tcref, [_; tagTy], _) when g.byref2_tcr.CanDeref -> tyconRefEq g g.byref2_tcr tcref && isOutByrefTag g tagTy @@ -2233,6 +2259,7 @@ and accFreeInTyparConstraint opts tpc acc = | TyparConstraint.SupportsComparison _ | TyparConstraint.SupportsEquality _ | TyparConstraint.SupportsNull _ + | TyparConstraint.NotSupportsNull _ | TyparConstraint.IsNonNullableStruct _ | TyparConstraint.IsReferenceType _ | TyparConstraint.IsUnmanaged _ @@ -2368,6 +2395,7 @@ and accFreeInTyparConstraintLeftToRight g cxFlag thruFlag acc tpc = | TyparConstraint.SupportsComparison _ | TyparConstraint.SupportsEquality _ | TyparConstraint.SupportsNull _ + | TyparConstraint.NotSupportsNull _ | TyparConstraint.IsNonNullableStruct _ | TyparConstraint.IsUnmanaged _ | TyparConstraint.IsReferenceType _ @@ -2416,7 +2444,7 @@ and accFreeInTypeLeftToRight g cxFlag thruFlag acc ty = let racc = accFreeInTypeLeftToRight g cxFlag thruFlag emptyFreeTyparsLeftToRight r unionFreeTyparsLeftToRight (boundTyparsLeftToRight g cxFlag thruFlag tps racc) acc - | TType_measure unt -> + | TType_measure unt -> let mvars = ListMeasureVarOccsWithNonZeroExponents unt List.foldBack (fun (tp, _) acc -> accFreeTyparRefLeftToRight g cxFlag thruFlag acc tp) mvars acc @@ -2754,7 +2782,10 @@ let generalizedTyconRef (g: TcGlobals) tcref = let tinst = generalTyconRefInst tcref TType_app(tcref, tinst, g.knownWithoutNull) -let isTTyparCoercesToType = function TyparConstraint.CoercesTo _ -> true | _ -> false +let isTTyparCoercesToType tpc = + match tpc with + | TyparConstraint.CoercesTo _ -> true + | _ -> false //-------------------------------------------------------------------------- // Print Signatures/Types - prelude @@ -3878,32 +3909,44 @@ module DebugPrint = else tupleL tinstL ^^ tcL + and auxAddNullness coreL (nullness: Nullness) = + match nullness.Evaluate() with + | NullnessInfo.WithNull -> coreL ^^ wordL (tagText "?") + | NullnessInfo.WithoutNull -> coreL + | NullnessInfo.AmbivalentToNull -> coreL //^^ wordL (tagText "%") + and auxTypeWrapL env isAtomic ty = let wrap x = bracketIfL isAtomic x in // wrap iff require atomic expr match stripTyparEqns ty with | TType_forall (typars, bodyTy) -> (leftL (tagText "!") ^^ layoutTyparDecls typars --- auxTypeL env bodyTy) |> wrap - | TType_ucase (UnionCaseRef(tcref, _), tinst) - - | TType_app (tcref, tinst, _) -> + | TType_ucase (UnionCaseRef(tcref, _), tinst) -> let prefix = tcref.IsPrefixDisplay let tcL = layoutTyconRef tcref auxTyparsL env tcL prefix tinst + | TType_app (tcref, tinst, nullness) -> + let prefix = tcref.IsPrefixDisplay + let tcL = layoutTyconRef tcref + let coreL = auxTyparsL env tcL prefix tinst + auxAddNullness coreL nullness + | TType_tuple (_tupInfo, tys) -> sepListL (wordL (tagText "*")) (List.map (auxTypeAtomL env) tys) |> wrap - | TType_fun (domainTy, rangeTy, _) -> - ((auxTypeAtomL env domainTy ^^ wordL (tagText "->")) --- auxTypeL env rangeTy) |> wrap + | TType_fun (domainTy, rangeTy, nullness) -> + let coreL = ((auxTypeAtomL env domainTy ^^ wordL (tagText "->")) --- auxTypeL env rangeTy) |> wrap + auxAddNullness coreL nullness - | TType_var (typar, _) -> - auxTyparWrapL env isAtomic typar + | TType_var (typar, nullness) -> + let coreL = auxTyparWrapL env isAtomic typar + auxAddNullness coreL nullness | TType_anon (anonInfo, tys) -> - braceBarL (sepListL (wordL (tagText ";")) (List.map2 (fun nm ty -> wordL (tagField nm) --- auxTypeAtomL env ty) (Array.toList anonInfo.SortedNames) tys)) + braceBarL (sepListL (wordL (tagText ";")) (List.map2 (fun nm ty -> wordL (tagField nm) --- auxTypeAtomL env ty) (Array.toList anonInfo.SortedNames) tys)) - | TType_measure unt -> + | TType_measure unt -> #if DEBUG leftL (tagText "{") ^^ (match global_g with @@ -4003,6 +4046,8 @@ module DebugPrint = wordL (tagText "struct") |> constraintPrefix | TyparConstraint.IsReferenceType _ -> wordL (tagText "not struct") |> constraintPrefix + | TyparConstraint.NotSupportsNull _ -> + wordL (tagText "not null") |> constraintPrefix | TyparConstraint.IsUnmanaged _ -> wordL (tagText "unmanaged") |> constraintPrefix | TyparConstraint.SimpleChoice(tys, _) -> @@ -8850,15 +8895,34 @@ let TypeNullNever g ty = isByrefTy g underlyingTy || isNonNullableStructTyparTy g ty -/// Indicates if the type admits the use of 'null' as a value +let TyconRefNullIsExtraValueAux isNew g m (tcref: TyconRef) = + not tcref.IsStructOrEnumTycon && + not (isByrefLikeTyconRef g m tcref) && + (if tcref.IsILTycon then + // Putting AllowNullLiteralAttribute(false) on an IL or provided type means 'null' can't be used with that type + (not isNew && TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref <> Some false) + else +// Putting AllowNullLiteralAttribute(true) on an F# type means it always admits null even in the new model + (TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref = Some true)) + +let TyconRefNullIsExtraValue g m tcref = TyconRefNullIsExtraValueAux false g m tcref +let TyconRefNullIsExtraValueNew g m tcref = TyconRefNullIsExtraValueAux true g m tcref + +/// The F# 4.5 logic about whether a type admits the use of 'null' as a value. let TypeNullIsExtraValue g m ty = if isILReferenceTy g ty || isDelegateTy g ty then - // Putting AllowNullLiteralAttribute(false) on an IL or provided type means 'null' can't be used with that type - not (match tryTcrefOfAppTy g ty with ValueSome tcref -> TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref = Some false | _ -> false) + match tryTcrefOfAppTy g ty with + | ValueSome tcref -> + // In F# 4.x, putting AllowNullLiteralAttribute(false) on an IL or provided + // type means 'null' can't be used with that type, otherwise it can + TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref <> Some false + | _ -> + // In F# 4.5, other IL reference types (e.g. arrays) always support null + true elif TypeNullNever g ty then false else - // Putting AllowNullLiteralAttribute(true) on an F# type means 'null' can be used with that type + // In F# 4.x, putting AllowNullLiteralAttribute(true) on an F# type means 'null' can be used with that type match tryTcrefOfAppTy g ty with | ValueSome tcref -> TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref = Some true | ValueNone -> @@ -8869,12 +8933,33 @@ let TypeNullIsExtraValue g m ty = else false +/// The new logic about whether a type admits the use of 'null' as a value. +let TypeNullIsExtraValueNew g m ty = + let sty = stripTyparEqns ty + (match tryTcrefOfAppTy g sty with + | ValueSome tcref -> + not tcref.IsStructOrEnumTycon && + not (isByrefLikeTyconRef g m tcref) && + (TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref = Some true) + | _ -> false) + || + (match (nullnessOfTy g sty).Evaluate() with + | NullnessInfo.AmbivalentToNull -> false + | NullnessInfo.WithoutNull -> false + | NullnessInfo.WithNull -> true) + || + (isReferenceTyparTy g ty && + (destTyparTy g ty).Constraints |> List.exists (function TyparConstraint.SupportsNull _ -> true | _ -> false)) + +/// The F# 4.5 and 5.0 logic about whether a type uses 'null' as a true representation value let TypeNullIsTrueValue g ty = (match tryTcrefOfAppTy g ty with | ValueSome tcref -> IsUnionTypeWithNullAsTrueValue g tcref.Deref | _ -> false) || isUnitTy g ty +/// Indicates if unbox(null) is actively rejected at runtime. See nullability RFC. This applies to types that don't have null +/// as a valid runtime representation under old compatiblity rules. let TypeNullNotLiked g m ty = not (TypeNullIsExtraValue g m ty) && not (TypeNullIsTrueValue g ty) @@ -8884,15 +8969,11 @@ let TypeNullNotLiked g m ty = let TypeSatisfiesNullConstraint g m ty = TypeNullIsExtraValue g m ty -// The non-inferring counter-part to SolveTypeRequiresDefaultValue (and SolveTypeRequiresDefaultConstructor for struct types) -let rec TypeHasDefaultValue g m ty = +let rec TypeHasDefaultValueAux isNew g m ty = let ty = stripTyEqnsAndMeasureEqns g ty - // Check reference types - precisely the ones satisfying the ': null' constraint have default values - TypeSatisfiesNullConstraint g m ty - || - // Check nominal struct types - (isStructTy g ty && - // F# struct types have a DefaultValue if all their field types have a default value excluding those with DefaultValue(false) + (if isNew then TypeNullIsExtraValueNew g m ty else TypeNullIsExtraValue g m ty) + || (isStructTy g ty && + // Is it an F# struct type? (if isFSharpStructTy g ty then let tcref, tinst = destAppTy g ty let flds = @@ -8901,17 +8982,17 @@ let rec TypeHasDefaultValue g m ty = // We can ignore fields with the DefaultValue(false) attribute |> List.filter (fun fld -> not (TryFindFSharpBoolAttribute g g.attrib_DefaultValueAttribute fld.FieldAttribs = Some false)) - flds |> List.forall (actualTyOfRecdField (mkTyconRefInst tcref tinst) >> TypeHasDefaultValue g m) + flds |> List.forall (actualTyOfRecdField (mkTyconRefInst tcref tinst) >> TypeHasDefaultValueAux isNew g m) // Struct tuple types have a DefaultValue if all their element types have a default value elif isStructTupleTy g ty then - destStructTupleTy g ty |> List.forall (TypeHasDefaultValue g m) + destStructTupleTy g ty |> List.forall (TypeHasDefaultValueAux isNew g m) // Struct anonymous record types have a DefaultValue if all their element types have a default value elif isStructAnonRecdTy g ty then match tryDestAnonRecdTy g ty with | ValueNone -> true - | ValueSome (_, ptys) -> ptys |> List.forall (TypeHasDefaultValue g m) + | ValueSome (_, ptys) -> ptys |> List.forall (TypeHasDefaultValueAux isNew g m) else // All nominal struct types defined in other .NET languages have a DefaultValue regardless of their instantiation true)) @@ -8920,6 +9001,10 @@ let rec TypeHasDefaultValue g m ty = (isNonNullableStructTyparTy g ty && (destTyparTy g ty).Constraints |> List.exists (function TyparConstraint.RequiresDefaultConstructor _ -> true | _ -> false)) +let TypeHasDefaultValue g m ty = TypeHasDefaultValueAux false g m ty + +let TypeHasDefaultValueNew g m ty = TypeHasDefaultValueAux true g m ty + /// Determines types that are potentially known to satisfy the 'comparable' constraint and returns /// a set of residual types that must also satisfy the constraint let (|SpecialComparableHeadType|_|) g ty = diff --git a/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi index 8582edaa5fc..1dee86e329b 100755 --- a/src/Compiler/TypedTree/TypedTreeOps.fsi +++ b/src/Compiler/TypedTree/TypedTreeOps.fsi @@ -635,6 +635,8 @@ val destMeasureTy: TcGlobals -> TType -> Measure val tryDestForallTy: TcGlobals -> TType -> Typars * TType +val nullnessOfTy: TcGlobals -> TType -> Nullness + val isFunTy: TcGlobals -> TType -> bool val isForallTy: TcGlobals -> TType -> bool @@ -1613,7 +1615,7 @@ val destArrayTy: TcGlobals -> TType -> TType val destListTy: TcGlobals -> TType -> TType /// Build an array type of the given rank -val mkArrayTy: TcGlobals -> int -> TType -> range -> TType +val mkArrayTy: TcGlobals -> int -> Nullness -> TType -> range -> TType /// Check if a type definition is one of the artificial type definitions used for array types of different ranks val isArrayTyconRef: TcGlobals -> TyconRef -> bool @@ -1738,15 +1740,19 @@ val ModuleNameIsMangled: TcGlobals -> Attribs -> bool val CompileAsEvent: TcGlobals -> Attribs -> bool +val TypeNullIsTrueValue: TcGlobals -> TType -> bool + +val TypeNullIsExtraValueNew: TcGlobals -> range -> TType -> bool + val TypeNullIsExtraValue: TcGlobals -> range -> TType -> bool -val TypeNullIsTrueValue: TcGlobals -> TType -> bool +val TyconRefNullIsExtraValue: TcGlobals -> range -> TyconRef -> bool -val TypeNullNotLiked: TcGlobals -> range -> TType -> bool +val TyconRefNullIsExtraValueNew: TcGlobals -> range -> TyconRef -> bool val TypeNullNever: TcGlobals -> TType -> bool -val TypeSatisfiesNullConstraint: TcGlobals -> range -> TType -> bool +val TypeHasDefaultValueNew: TcGlobals -> range -> TType -> bool val TypeHasDefaultValue: TcGlobals -> range -> TType -> bool diff --git a/src/Compiler/TypedTree/TypedTreePickle.fs b/src/Compiler/TypedTree/TypedTreePickle.fs index f7f98e5620b..880082e9a1d 100644 --- a/src/Compiler/TypedTree/TypedTreePickle.fs +++ b/src/Compiler/TypedTree/TypedTreePickle.fs @@ -121,6 +121,7 @@ type NodeOutTable<'Data, 'Node> = [] type WriterState = { os: ByteBuffer + osB: ByteBuffer oscope: CcuThunk occus: Table oentities: NodeOutTable @@ -154,6 +155,8 @@ type NodeInTable<'Data, 'Node> = [] type ReaderState = { is: ByteStream + // secondary stream of information for F# 5.0 + isB: ByteStream iilscope: ILScopeRef iccus: InputTable ientities: NodeInTable @@ -178,18 +181,28 @@ type 'T pickler = 'T -> WriterState -> unit let p_byte b st = st.os.EmitIntAsByte b +let p_byteB b st = st.osB.EmitIntAsByte b + let p_bool b st = p_byte (if b then 1 else 0) st -let prim_p_int32 i st = +/// Write an uncompressed integer to the main stream. +let prim_p_int32 i st = p_byte (b0 i) st p_byte (b1 i) st p_byte (b2 i) st p_byte (b3 i) st -/// Compress integers according to the same scheme used by CLR metadata -/// This halves the size of pickled data -let p_int32 n st = - if n >= 0 && n <= 0x7F then +/// Write an uncompressed integer to the B stream. +let prim_p_int32B i st = + p_byteB (b0 i) st + p_byteB (b1 i) st + p_byteB (b2 i) st + p_byteB (b3 i) st + +/// Compress integers according to the same scheme used by CLR metadata +/// This halves the size of pickled data +let p_int32 n st = + if n >= 0 && n <= 0x7F then p_byte (b0 n) st else if n >= 0x80 && n <= 0x3FFF then p_byte (0x80 ||| (n >>> 8)) st @@ -198,6 +211,17 @@ let p_int32 n st = p_byte 0xFF st prim_p_int32 n st +/// Write a compressed integer to the B stream. +let p_int32B n st = + if n >= 0 && n <= 0x7F then + p_byteB (b0 n) st + else if n >= 0x80 && n <= 0x3FFF then + p_byteB ( (0x80 ||| (n >>> 8))) st + p_byteB ( (n &&& 0xFF)) st + else + p_byteB 0xFF st + prim_p_int32B n st + let space = () let p_space n () st = for i = 0 to n - 1 do @@ -227,6 +251,7 @@ let p_prim_string (s: string) st = st.os.EmitBytes bytes let p_int c st = p_int32 c st +let p_intB c st = p_int32B c st let p_int8 (i: sbyte) st = p_int32 (int32 i) st let p_uint8 (i: byte) st = p_byte (int i) st let p_int16 (i: int16) st = p_int32 (int32 i) st @@ -267,12 +292,16 @@ let inline p_tup11 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 (a, b, c, d, e, f, x7, x8 let u_byte st = int (st.is.ReadByte()) +/// Unpickle an uncompressed integer from the B stream +/// The extra B stream of bytes is implicitly 0 if not present +let u_byteB st = + if st.isB.IsEOF then 0 else int (st.isB.ReadByte()) + type unpickler<'T> = ReaderState -> 'T let u_bool st = let b = u_byte st in (b = 1) - - +/// Unpickle an uncompressed integer from the main stream let prim_u_int32 st = let b0 = (u_byte st) let b1 = (u_byte st) @@ -280,6 +309,14 @@ let prim_u_int32 st = let b3 = (u_byte st) b0 ||| (b1 <<< 8) ||| (b2 <<< 16) ||| (b3 <<< 24) +/// Unpickle an uncompressed integer from the B stream +let prim_u_int32B st = + let b0 = u_byteB st + let b1 = u_byteB st + let b2 = u_byteB st + let b3 = u_byteB st + b0 ||| (b1 <<< 8) ||| (b2 <<< 16) ||| (b3 <<< 24) + let u_int32 st = let b0 = u_byte st if b0 <= 0x7F then b0 @@ -291,6 +328,19 @@ let u_int32 st = assert(b0 = 0xFF) prim_u_int32 st +/// Unpickle a compressed integer from the B stream. +/// The integer is 0 if the B stream is not present. +let u_int32B st = + let b0 = u_byteB st + if b0 <= 0x7F then b0 + else if b0 <= 0xbf then + let b0 = b0 &&& 0x7F + let b1 = u_byteB st + (b0 <<< 8) ||| b1 + else + assert(b0 = 0xFF) + prim_u_int32B st + let u_byte_memory st = let n = (u_int32 st) st.is.ReadBytes n @@ -303,6 +353,7 @@ let u_prim_string st = st.is.ReadUtf8String len let u_int st = u_int32 st +let u_intB st = u_int32B st let u_int8 st = sbyte (u_int32 st) let u_uint8 st = byte (u_byte st) let u_int16 st = int16 (u_int32 st) @@ -444,7 +495,12 @@ let p_list_core f (xs: 'T list) st = let p_list f x st = p_int (List.length x) st p_list_core f x st -let p_list_ext extraf f x st = + +let p_listB f x st = + p_intB (List.length x) st + p_list_core f x st + +let p_list_ext extraf f x st = let n = List.length x let n = if Option.isSome extraf then n ||| 0x80000000 else n p_int n st @@ -530,6 +586,12 @@ let u_list_core f n st = let u_list f st = let n = u_int st u_list_core f n st + +/// Unpickle a list from the B stream. The resulting list is empty if the B stream is not present. +let u_listB f st = + let n = u_intB st + u_list_core f n st + let u_list_ext extra f st = let n = u_int st let extraItem = @@ -682,7 +744,12 @@ let p_nleref x st = p_int (encode_nleref st.occus st.ostrings st.onlerefs st.osc // Simple types are types like "int", represented as TType(Ref_nonlocal(..., "int"), []). // A huge number of these occur in pickled F# data, so make them unique. -let decode_simpletyp st _ccuTab _stringTab nlerefTab a = TType_app(ERefNonLocal (lookup_nleref st nlerefTab a), [], 0uy) +// +// NULLNESS - the simpletyp table now holds KnownAmbivalentToNull by default. +// For old assemblies it is, if we give those assemblies the ambivalent interpretation. +// For new asemblies compiled with null-checking on it isn't, if the default is to give +// those the KnownWithoutNull interpretation by default. +let decode_simpletyp st _ccuTab _stringTab nlerefTab a = TType_app(ERefNonLocal (lookup_nleref st nlerefTab a), [], KnownAmbivalentToNull) let u_encoded_simpletyp st = u_int st let u_simpletyp st = lookup_uniq st st.isimpletys (u_int st) let encode_simpletyp ccuTab stringTab nlerefTab simpleTyTab thisCcu a = encode_uniq simpleTyTab (encode_nleref ccuTab stringTab nlerefTab thisCcu a) @@ -696,6 +763,7 @@ let PickleBufferCapacity = 50000 let pickleObjWithDanglingCcus inMem file g scope p x = let st1 = { os = ByteBuffer.Create(PickleBufferCapacity, useArrayPool = true) + osB = ByteBuffer.Create(PickleBufferCapacity, useArrayPool = true) oscope=scope occus= Table<_>.Create "occus" oentities=NodeOutTable<_, _>.Create((fun (tc: Tycon) -> tc.Stamp), (fun tc -> tc.LogicalName), (fun tc -> tc.Range), id , "otycons") @@ -709,22 +777,24 @@ let pickleObjWithDanglingCcus inMem file g scope p x = oglobals=g ofile=file oInMem=inMem - isStructThisArgPos = false} - let ccuNameTab, (ntycons, ntypars, nvals, nanoninfos), stringTab, pubpathTab, nlerefTab, simpleTyTab, phase1bytes = + isStructThisArgPos = false } + + let ccuNameTab,(ntycons, ntypars, nvals, nanoninfos),stringTab,pubpathTab,nlerefTab,simpleTyTab,phase1bytes,phase1bytesB = p x st1 let sizes = st1.oentities.Size, st1.otypars.Size, st1.ovals.Size, st1.oanoninfos.Size - st1.occus, sizes, st1.ostrings, st1.opubpaths, st1.onlerefs, st1.osimpletys, st1.os.AsMemory() + st1.occus, sizes, st1.ostrings, st1.opubpaths, st1.onlerefs, st1.osimpletys, st1.os.AsMemory(), st1.osB let st2 = { os = ByteBuffer.Create(PickleBufferCapacity, useArrayPool = true) + osB = ByteBuffer.Create(PickleBufferCapacity, useArrayPool = true) oscope=scope occus= Table<_>.Create "occus (fake)" - oentities=NodeOutTable<_, _>.Create((fun (tc: Tycon) -> tc.Stamp), (fun tc -> tc.LogicalName), (fun tc -> tc.Range), id , "otycons") - otypars=NodeOutTable<_, _>.Create((fun (tp: Typar) -> tp.Stamp), (fun tp -> tp.DisplayName), (fun tp -> tp.Range), id , "otypars") + oentities=NodeOutTable<_, _>.Create((fun (tc: Tycon) -> tc.Stamp), (fun tc -> tc.LogicalName), (fun tc -> tc.Range), id, "otycons") + otypars=NodeOutTable<_, _>.Create((fun (tp: Typar) -> tp.Stamp), (fun tp -> tp.DisplayName), (fun tp -> tp.Range), id, "otypars") ovals=NodeOutTable<_, _>.Create((fun (v: Val) -> v.Stamp), (fun v -> v.LogicalName), (fun v -> v.Range), (fun osgn -> osgn), "ovals") oanoninfos=NodeOutTable<_, _>.Create((fun (v: AnonRecdTypeInfo) -> v.Stamp), (fun v -> string v.Stamp), (fun _ -> range0), id, "oanoninfos") ostrings=Table<_>.Create "ostrings (fake)" @@ -752,12 +822,18 @@ let pickleObjWithDanglingCcus inMem file g scope p x = p_memory (stringTab.AsArray, pubpathTab.AsArray, nlerefTab.AsArray, simpleTyTab.AsArray, phase1bytes) st2 + + // The B stream should be empty in the second phase + let phase2bytesB = st2.osB.AsMemory() + if phase2bytesB.Length <> 0 then failwith "expected phase2bytesB.Length = 0" + (st2.osB :> System.IDisposable).Dispose() st2.os (st1.os :> System.IDisposable).Dispose() - phase2bytes -let check (ilscope: ILScopeRef) (inMap: NodeInTable<_, _>) = + phase2bytes, phase1bytesB + +let check (ilscope: ILScopeRef) (inMap: NodeInTable<_,_>) = for i = 0 to inMap.Count - 1 do let n = inMap.Get i if not (inMap.IsLinked n) then @@ -767,9 +843,10 @@ let check (ilscope: ILScopeRef) (inMap: NodeInTable<_, _>) = // an identical copy of the source for the DLL containing the data being unpickled. A message will // then be printed indicating the name of the item. -let unpickleObjWithDanglingCcus file viewedScope (ilModule: ILModuleDef option) u (phase2bytes: ReadOnlyByteMemory) = +let unpickleObjWithDanglingCcus file viewedScope (ilModule: ILModuleDef option) u (phase2bytes: ReadOnlyByteMemory) (phase1bytesB: ReadOnlyByteMemory) = let st2 = { is = ByteStream.FromBytes (phase2bytes, 0, phase2bytes.Length) + isB = ByteStream.FromBytes (ByteMemory.FromArray([| |]).AsReadOnly(), 0, 0) iilscope = viewedScope iccus = new_itbl "iccus (fake)" [| |] ientities = NodeInTable<_, _>.Create (Tycon.NewUnlinked, (fun osgn tg -> osgn.Link tg), (fun osgn -> osgn.IsLinked), "itycons", 0) @@ -803,6 +880,7 @@ let unpickleObjWithDanglingCcus file viewedScope (ilModule: ILModuleDef option) let data = let st1 = { is = ByteStream.FromBytes (phase1bytes, 0, phase1bytes.Length) + isB = ByteStream.FromBytes (phase1bytesB, 0, phase1bytesB.Length) iccus = ccuTab iilscope = viewedScope ientities = NodeInTable<_, _>.Create(Tycon.NewUnlinked, (fun osgn tg -> osgn.Link tg), (fun osgn -> osgn.IsLinked), "itycons", ntycons) @@ -817,6 +895,7 @@ let unpickleObjWithDanglingCcus file viewedScope (ilModule: ILModuleDef option) iILModule = ilModule } let res = u st1 check viewedScope st1.ientities + check viewedScope st1.ientities check viewedScope st1.ivals check viewedScope st1.itypars res @@ -1564,7 +1643,20 @@ let p_tyar_constraint x st = | TyparConstraint.SupportsComparison _ -> p_byte 10 st | TyparConstraint.SupportsEquality _ -> p_byte 11 st | TyparConstraint.IsUnmanaged _ -> p_byte 12 st -let p_tyar_constraints = (p_list p_tyar_constraint) + | TyparConstraint.NotSupportsNull _ -> + failwith "NotSupportsNull constraints should only be emitted to streamB" + +// Some extra F# 5.0 constraints are stored in stream B, these will be ignored by earlier F# compilers +let p_tyar_constraintB x st = + match x with + | TyparConstraint.NotSupportsNull _ -> p_byteB 1 st + | _ -> failwith "only NotSupportsNull constraints should be emitted to streamB" + +let p_tyar_constraints cxs st = + let cxs1, cxs2 = cxs |> List.partition (function TyparConstraint.NotSupportsNull _ -> false | _ -> true) + p_list p_tyar_constraint cxs1 st + // Some extra F# 5.0 constraints are stored in stream B, these will be ignored by earlier F# compilers + p_listB p_tyar_constraintB cxs2 st let u_tyar_constraint st = let tag = u_byte st @@ -1584,9 +1676,21 @@ let u_tyar_constraint st = | 12 -> (fun _ -> TyparConstraint.IsUnmanaged range0) | _ -> ufailwith st "u_tyar_constraint" - -let u_tyar_constraints = (u_list_revi u_tyar_constraint) - +// Some extra F# 5.0 constraints are stored in stream B, these will be ignored by earlier F# compilers +let u_tyar_constraintB st = + let tag = u_byteB st + match tag with + | 1 -> TyparConstraint.NotSupportsNull range0 + | _ -> ufailwith st "u_tyar_constraintB - unexpected constraint in streamB" + +let u_tyar_constraints st = + let cxs1 = u_list_revi u_tyar_constraint st + // Some extra F# 5.0 constraints are stored in stream B, these will be ignored by earlier F# compilers + // + // If the B stream is not present (e.g. reading F# 4.5 components) then this list will be empty + // via the implementation of u_listB. + let cxs2 = u_listB u_tyar_constraintB st + cxs1 @ cxs2 let p_tyar_spec_data (x: Typar) st = p_tup5 @@ -1639,19 +1743,41 @@ let _ = fill_p_ty2 (fun isStructThisArgPos ty st -> else p_byte 0 st; p_tys l st - | TType_app(ERefNonLocal nleref, [], _) -> + | TType_app(ERefNonLocal nleref, [], nullness) -> + if st.oglobals.langFeatureNullness then + match nullness.Evaluate() with + | NullnessInfo.WithNull -> p_byteB 9 st + | NullnessInfo.WithoutNull -> p_byteB 10 st + | NullnessInfo.AmbivalentToNull -> p_byteB 11 st p_byte 1 st; p_simpletyp nleref st - | TType_app (tc, tinst, _) -> - p_byte 2 st; p_tup2 (p_tcref "typ") p_tys (tc, tinst) st - - | TType_fun (d, r, _) -> + | TType_app (tc, tinst, nullness) -> + if st.oglobals.langFeatureNullness then + match nullness.Evaluate() with + | NullnessInfo.WithNull -> p_byteB 12 st + | NullnessInfo.WithoutNull -> p_byteB 13 st + | NullnessInfo.AmbivalentToNull -> p_byteB 14 st + p_byte 2 st; p_tcref "typ" tc st; p_tys tinst st + + | TType_fun (d,r,nullness) -> + if st.oglobals.langFeatureNullness then + match nullness.Evaluate() with + | NullnessInfo.WithNull -> p_byteB 15 st + | NullnessInfo.WithoutNull -> p_byteB 16 st + | NullnessInfo.AmbivalentToNull -> p_byteB 17 st p_byte 3 st // Note, the "this" argument may be found in the domain position of a function type, so propagate the isStructThisArgPos value p_ty2 isStructThisArgPos d st p_ty r st - | TType_var (r, _) -> p_byte 4 st; p_tpref r st + | TType_var (r, nullness) -> + if st.oglobals.langFeatureNullness then + match nullness.Evaluate() with + | NullnessInfo.WithNull -> p_byteB 18 st + | NullnessInfo.WithoutNull -> p_byteB 19 st + | NullnessInfo.AmbivalentToNull -> p_byteB 20 st + p_byte 4 st + p_tpref r st | TType_forall (tps, r) -> p_byte 5 st @@ -1677,27 +1803,59 @@ let _ = fill_p_ty2 (fun isStructThisArgPos ty st -> let _ = fill_u_ty (fun st -> let tag = u_byte st + match tag with | 0 -> let l = u_tys st TType_tuple (tupInfoRef, l) - - | 1 -> - u_simpletyp st - - | 2 -> - let tc = u_tcref st + | 1 -> + let tagB = u_byteB st + let sty = u_simpletyp st + match tagB with + | 0 -> + sty + | 9 -> + match sty with + | TType_app(tcref, _, _) -> TType_app(tcref, [], KnownWithNull) + | _ -> ufailwith st "u_ty 9a" + | 10 -> + match sty with + | TType_app(tcref, _, _) -> TType_app(tcref, [], KnownWithoutNull) + | _ -> ufailwith st "u_ty 9b" + | 11 -> + match sty with + | TType_app(tcref, _, _) -> TType_app(tcref, [], KnownAmbivalentToNull) + | _ -> ufailwith st "u_ty 9c" + | b -> ufailwith st (sprintf "u_ty - 1/B, byte = %A" b) + | 2 -> + let tagB = u_byteB st + let tcref = u_tcref st let tinst = u_tys st - TType_app (tc, tinst, 0uy) - - | 3 -> + match tagB with + | 0 -> TType_app (tcref, tinst, KnownAmbivalentToNull) + | 12 -> TType_app (tcref, tinst, KnownWithNull) + | 13 -> TType_app (tcref, tinst, KnownWithoutNull) + | 14 -> TType_app (tcref, tinst, KnownAmbivalentToNull) + | _ -> ufailwith st "u_ty - 2/B" + | 3 -> + let tagB = u_byteB st let d = u_ty st let r = u_ty st - TType_fun (d, r, 0uy) - + match tagB with + | 0 -> TType_fun (d, r, KnownAmbivalentToNull) + | 15 -> TType_fun (d, r, KnownWithNull) + | 16 -> TType_fun (d, r, KnownWithoutNull) + | 17 -> TType_fun (d, r, KnownAmbivalentToNull) + | _ -> ufailwith st "u_ty - 3/B" | 4 -> + let tagB = u_byteB st let r = u_tpref st - r.AsType + match tagB with + | 0 -> r.AsType KnownAmbivalentToNull + | 18 -> r.AsType KnownWithNull + | 19 -> r.AsType KnownWithoutNull + | 20 -> r.AsType KnownAmbivalentToNull + | _ -> ufailwith st "u_ty - 4/B" | 5 -> let tps = u_tyar_specs st diff --git a/src/Compiler/TypedTree/TypedTreePickle.fsi b/src/Compiler/TypedTree/TypedTreePickle.fsi index 2d6fc2bdc4d..66a0017c001 100644 --- a/src/Compiler/TypedTree/TypedTreePickle.fsi +++ b/src/Compiler/TypedTree/TypedTreePickle.fsi @@ -85,7 +85,7 @@ val internal pickleCcuInfo: pickler /// Serialize an arbitrary object using the given pickler val pickleObjWithDanglingCcus: - inMem: bool -> file: string -> TcGlobals -> scope: CcuThunk -> pickler<'T> -> 'T -> ByteBuffer + inMem: bool -> file: string -> TcGlobals -> scope: CcuThunk -> pickler<'T> -> 'T -> ByteBuffer * ByteBuffer /// The type of state unpicklers read from type ReaderState @@ -151,5 +151,6 @@ val internal unpickleObjWithDanglingCcus: viewedScope: ILScopeRef -> ilModule: ILModuleDef option -> 'T unpickler -> + ReadOnlyByteMemory -> ReadOnlyByteMemory -> PickledDataWithReferences<'T> diff --git a/src/Compiler/TypedTree/tainted.fs b/src/Compiler/TypedTree/tainted.fs index 0eb274fa48b..0c825c3a11b 100644 --- a/src/Compiler/TypedTree/tainted.fs +++ b/src/Compiler/TypedTree/tainted.fs @@ -131,8 +131,8 @@ type internal Tainted<'T> (context: TaintedContext, value: 'T) = let u = this.Protect (fun x -> f (x, context.TypeProvider)) range Tainted(context, u) - member this.PApplyArray(f, methodName, range: range) = - let a : 'U[] = this.Protect f range + member this.PApplyArray(f, methodName, range:range) = + let a : 'U[] MaybeNull = this.Protect f range match a with | Null -> raise <| TypeProviderError(FSComp.SR.etProviderReturnedNull(methodName), this.TypeProviderDesignation, range) | NonNull a -> a |> Array.map (fun u -> Tainted(context,u)) @@ -163,8 +163,14 @@ type internal Tainted<'T> (context: TaintedContext, value: 'T) = Tainted(context, this.Protect(fun value -> box value :?> 'U) range) module internal Tainted = - let (|Null|NonNull|) (p:Tainted<'T>) : Choice> when 'T : null and 'T : not struct = + +#if NO_CHECKNULLS + let (|Null|NonNull|) (p:Tainted<'T>) : Choice> when 'T : null and 'T : not struct = if p.PUntaintNoFailure isNull then Null else NonNull (p.PApplyNoFailure id) +#else + let (|Null|NonNull|) (p:Tainted<'T __withnull>) : Choice> when 'T : __notnull and 'T : not struct = + if p.PUntaintNoFailure isNull then Null else NonNull (p.PApplyNoFailure nonNull) +#endif let Eq (p:Tainted<'T>) (v:'T) = p.PUntaintNoFailure (fun pv -> pv = v) diff --git a/src/Compiler/TypedTree/tainted.fsi b/src/Compiler/TypedTree/tainted.fsi index ee1a6d94069..8ad58f6f265 100644 --- a/src/Compiler/TypedTree/tainted.fsi +++ b/src/Compiler/TypedTree/tainted.fsi @@ -101,7 +101,11 @@ type internal Tainted<'T> = module internal Tainted = /// Test whether the tainted value is null - val (|Null|NonNull|): Tainted<'T MaybeNull> -> Choice> when 'T: null and 'T: not struct +#if NO_CHECKNULLS + val (|Null|NonNull|) : Tainted<'T MaybeNull> -> Choice> when 'T : null and 'T : not struct +#else + val (|Null|NonNull|) : Tainted<'T MaybeNull> -> Choice> when 'T : __notnull and 'T : not struct +#endif /// Test whether the tainted value equals given value. /// Failure in call to equality operation will be blamed on type provider of first operand diff --git a/src/Compiler/Utilities/illib.fs b/src/Compiler/Utilities/illib.fs index 8dbf5fd4534..7942b78593e 100644 --- a/src/Compiler/Utilities/illib.fs +++ b/src/Compiler/Utilities/illib.fs @@ -37,10 +37,11 @@ module internal PervasiveAutoOpens = | [ _ ] -> true | _ -> false - type 'T MaybeNull when 'T: null and 'T: not struct = 'T - let inline isNotNull (x: 'T) = not (isNull x) +#if NO_CHECKNULLS + type 'T MaybeNull when 'T: null and 'T: not struct = 'T + let inline (|NonNullQuick|) (x: 'T MaybeNull) = match x with | null -> raise (NullReferenceException()) @@ -60,6 +61,10 @@ module internal PervasiveAutoOpens = match x with | null -> raise (ArgumentNullException(paramName)) | v -> v +#else + type 'T MaybeNull when 'T: __notnull and 'T: not struct = 'T __withnull + +#endif let inline (===) x y = LanguagePrimitives.PhysicalEquality x y @@ -279,10 +284,7 @@ module Array = /// ~0.8x slower for ints let inline areEqual (xs: 'T[]) (ys: 'T[]) = match xs, ys with - | null, null -> true | [||], [||] -> true - | null, _ - | _, null -> false | _ when xs.Length <> ys.Length -> false | _ -> let mutable break' = false diff --git a/src/Compiler/Utilities/illib.fsi b/src/Compiler/Utilities/illib.fsi index 7272dace378..b2dabd69fde 100644 --- a/src/Compiler/Utilities/illib.fsi +++ b/src/Compiler/Utilities/illib.fsi @@ -26,6 +26,7 @@ module internal PervasiveAutoOpens = /// Returns true if the argument is non-null. val inline isNotNull: x: 'T -> bool when 'T: null +#if NO_CHECKNULLS /// Indicates that a type may be null. 'MaybeNull' is used internally in the F# compiler as /// replacement for 'string?' to align with FS-1060. type 'T MaybeNull when 'T: null and 'T: not struct = 'T @@ -41,6 +42,11 @@ module internal PervasiveAutoOpens = /// Checks the argument is non-null val inline nullArgCheck: paramName: string -> x: 'T MaybeNull -> 'T +#else + /// Indicates that a type may be null. 'MaybeNull' used internally in the F# compiler as unchecked + /// replacement for 'string?' + type 'T MaybeNull when 'T: __notnull and 'T: not struct = 'T __withnull +#endif val inline (===): x: 'a -> y: 'a -> bool when 'a: not struct diff --git a/src/Compiler/Utilities/lib.fs b/src/Compiler/Utilities/lib.fs index f4c37de4cf9..fd13790a90e 100755 --- a/src/Compiler/Utilities/lib.fs +++ b/src/Compiler/Utilities/lib.fs @@ -332,15 +332,15 @@ type Graph<'Data, 'Id when 'Id : comparison and 'Id : equality> // with care. //---------------------------------------------------------------------------- -type NonNullSlot<'T> = 'T -let nullableSlotEmpty() = Unchecked.defaultof<'T> -let nullableSlotFull x = x +type NonNullSlot<'T when 'T : not struct> = 'T +let nullableSlotEmpty() : NonNullSlot<'T> = Unchecked.defaultof<_> +let nullableSlotFull (x: 'T) : NonNullSlot<'T> = x //--------------------------------------------------------------------------- // Caches, mainly for free variables //--------------------------------------------------------------------------- -type cache<'T> = { mutable cacheVal: 'T NonNullSlot } +type cache<'T when 'T : not struct> = { mutable cacheVal: NonNullSlot<'T> } let newCache() = { cacheVal = nullableSlotEmpty() } let inline cached cache resF = diff --git a/src/Compiler/Utilities/lib.fsi b/src/Compiler/Utilities/lib.fsi index 2e6b0318f7a..a8f41f0cfd8 100644 --- a/src/Compiler/Utilities/lib.fsi +++ b/src/Compiler/Utilities/lib.fsi @@ -228,24 +228,24 @@ type Graph<'Data, 'Id when 'Id: comparison> = /// This is an unsafe trick, as it relies on the fact that the type of values /// being placed into the slot never utilizes "null" as a representation. To be used with /// with care. -type NonNullSlot<'T> = 'T +type NonNullSlot<'T when 'T: not struct> = 'T -val nullableSlotEmpty: unit -> 'T +val nullableSlotEmpty: unit -> NonNullSlot<'T> -val nullableSlotFull: x: 'a -> 'a +val nullableSlotFull: x: 'a -> NonNullSlot<'a> /// Caches, mainly for free variables -type cache<'T> = { mutable cacheVal: NonNullSlot<'T> } +type cache<'T when 'T: not struct> = { mutable cacheVal: NonNullSlot<'T> } -val newCache: unit -> cache<'a> +val newCache: unit -> cache<'a> when 'a: not struct -val inline cached: cache: cache<'a> -> resF: (unit -> 'a) -> 'a +val inline cached: cache: cache<'a> -> resF: (unit -> 'a) -> 'a when 'a: not struct val inline cacheOptByref: cache: byref<'T option> -> f: (unit -> 'T) -> 'T val inline cacheOptRef: cache: 'a option ref -> f: (unit -> 'a) -> 'a -val inline tryGetCacheValue: cache: cache<'a> -> NonNullSlot<'a> voption +val inline tryGetCacheValue: cache: cache<'a> -> NonNullSlot<'a> voption when 'a: not struct module UnmanagedProcessExecutionOptions = val EnableHeapTerminationOnCorruption: unit -> unit diff --git a/src/Compiler/Utilities/sformat.fs b/src/Compiler/Utilities/sformat.fs index 5d42dae0b45..bb119712d5a 100644 --- a/src/Compiler/Utilities/sformat.fs +++ b/src/Compiler/Utilities/sformat.fs @@ -116,6 +116,13 @@ type IEnvironment = abstract MaxColumns: int abstract MaxRows: int +#if NO_CHECKNULLS +[] +module NullShim = + // Shim to match nullness checking library support in preview + let inline (|Null|NonNull|) (x: 'T) : Choice = match x with null -> Null | v -> NonNull v +#endif + [] module TaggedText = let mkTag tag text = TaggedText(tag, text) @@ -491,7 +498,7 @@ module ReflectUtils = // of an F# value. let GetValueInfoOfObject (bindingFlags: BindingFlags) (obj: obj) = match obj with - | null -> NullValue + | Null -> NullValue | _ -> let reprty = obj.GetType() @@ -556,9 +563,8 @@ module ReflectUtils = let GetValueInfo bindingFlags (x: 'a, ty: Type) (* x could be null *) = let obj = (box x) - match obj with - | null -> + | Null -> let isNullaryUnion = match ty.GetCustomAttributes(typeof, false) with | [| :? CompilationRepresentationAttribute as attr |] -> @@ -576,7 +582,8 @@ module ReflectUtils = UnitValue else NullValue - | _ -> GetValueInfoOfObject bindingFlags obj + | NonNull obj -> + GetValueInfoOfObject bindingFlags obj module Display = open ReflectUtils @@ -836,8 +843,8 @@ module Display = let getListValueInfo bindingFlags (x: obj, ty: Type) = match x with - | null -> None - | _ -> + | Null -> None + | NonNull x -> match Value.GetValueInfo bindingFlags (x, ty) with | UnionCaseValue ("Cons", recd) -> Some(unpackCons recd) | UnionCaseValue ("Empty", [||]) -> None @@ -986,14 +993,13 @@ module Display = and objL showMode depthLim prec (x: obj, ty: Type) = let info = Value.GetValueInfo bindingFlags (x, ty) - try if depthLim <= 0 || exceededPrintSize () then wordL (tagPunctuation "...") else match x with - | null -> reprL showMode (depthLim - 1) prec info x - | _ -> + | Null -> reprL showMode (depthLim - 1) prec info x + | NonNull x -> if (path.ContainsKey(x)) then wordL (tagPunctuation "...") else @@ -1007,10 +1013,9 @@ module Display = Some(wordL (tagText (x.ToString()))) else // Try the StructuredFormatDisplayAttribute extensibility attribute - match ty.GetCustomAttributes(typeof, true) with - | null - | [||] -> None - | res -> structuredFormatObjectL showMode ty depthLim (res[0] :?> StructuredFormatDisplayAttribute) x + match ty.GetCustomAttributes (typeof, true) with + | Null | [| |] -> None + | NonNull res -> structuredFormatObjectL showMode ty depthLim (res[0] :?> StructuredFormatDisplayAttribute) x #if COMPILER // This is the PrintIntercepts extensibility point currently revealed by fsi.exe's AddPrinter @@ -1043,8 +1048,7 @@ module Display = // Format an object that has a layout specified by StructuredFormatAttribute and structuredFormatObjectL showMode ty depthLim (attr: StructuredFormatDisplayAttribute) (obj: obj) = let txt = attr.Value - - if isNull txt || txt.Length <= 1 then + if isNull (box txt) || txt.Length <= 1 then None else let messageRegexPattern = @"^(?
.*?)(?.*?)(?.*)$"
@@ -1514,7 +1518,7 @@ module Display =
 
     let leafFormatter (opts: FormatOptions) (obj: obj) =
         match obj with
-        | null -> tagKeyword "null"
+        | Null -> tagKeyword "null"
         | :? double as d ->
             let s = d.ToString(opts.FloatingPointFormat, opts.FormatProvider)
 
diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy
index 3d460406c80..29c6bb5071f 100644
--- a/src/Compiler/pars.fsy
+++ b/src/Compiler/pars.fsy
@@ -89,6 +89,7 @@ let parse_error_rich = Some(fun (ctxt: ParseErrorContext<_>) ->
 %token GREATER_RBRACK STRUCT SIG
 %token STATIC MEMBER CLASS ABSTRACT OVERRIDE DEFAULT CONSTRUCTOR INHERIT
 %token EXTERN VOID PUBLIC PRIVATE INTERNAL GLOBAL
+%token MAYBENULL__ NOTNULL__ WITHNULL__
 
 /* for parser 'escape hatch' out of expression context without consuming the 'recover' token */
 %token TYPE_COMING_SOON TYPE_IS_HERE MODULE_COMING_SOON MODULE_IS_HERE
@@ -1546,21 +1547,22 @@ tyconDefn:
            SynTypeDefn($1, SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.None($1.Range), $1.Range), [], None, $1.Range, trivia) }
 
   | typeNameInfo opt_equals tyconDefnRhsBlock
-     { match $2 with
-       | Some _ -> ()
-       | None ->
-            let (SynComponentInfo(_, _, _, lid, _, _, _, _)) = $1
-            // While the spec doesn't allow long idents here, the parser doesn't enforce this, so take one ident
-            let typeNameId = List.last lid
-            raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsEqualsMissingInTypeDefinition(typeNameId.ToString()))
+     { //match $2 with
+       //| Some _ -> ()
+       //| None ->
+       //     let (SynComponentInfo(_, _, _, lid, _, _, _, _)) = $1
+       //     // While the spec doesn't allow long idents here, the parser doesn't enforce this, so take one ident
+       //     let typeNameId = List.last lid
+       //     raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsEqualsMissingInTypeDefinition(typeNameId.ToString()))
 
        let nameRange = rhs parseState 1
        let (tcDefRepr: SynTypeDefnRepr), mWith, members = $3 nameRange
        let declRange = unionRanges (rhs parseState 1) tcDefRepr.Range
        let mWhole = (declRange, members) ||> unionRangeWithListBy (fun (mem: SynMemberDefn) -> mem.Range)
+       let mEquals = rhs parseState 2
 
        fun leadingKeyword ->
-           let trivia: SynTypeDefnTrivia = { LeadingKeyword = leadingKeyword; EqualsRange = $2; WithKeyword = mWith }
+           let trivia: SynTypeDefnTrivia = { LeadingKeyword = leadingKeyword; EqualsRange = Some mEquals; WithKeyword = mWith }
            SynTypeDefn($1, tcDefRepr, members, None, mWhole, trivia) }
 
   | typeNameInfo tyconDefnAugmentation
@@ -2311,11 +2313,20 @@ typeConstraint:
      { SynTypeConstraint.WhereTyparIsValueType($1, lhs parseState) }
 
   | typar COLON IDENT STRUCT
-     { if $3 <> "not" then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier($3))
+     { if $3 <> "not" then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier($3 + " (1)"))
        SynTypeConstraint.WhereTyparIsReferenceType($1, lhs parseState) }
 
   | typar COLON NULL
      { SynTypeConstraint.WhereTyparSupportsNull($1, lhs parseState) }
+/*
+** TODO: This rule is not triggering, faking it with __notnull for now
+
+  | typar COLON IDENT NULL
+      { if $3 <> "not" then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier($3 + " (2)"))  
+        SynTypeConstraint.WhereTyparNotSupportsNull($1, lhs parseState) }
+*/
+  | typar COLON NOTNULL__
+      { SynTypeConstraint.WhereTyparNotSupportsNull($1, lhs parseState) }
 
   | typar COLON LPAREN classMemberSpfn rparen
      { let tp = $1
@@ -2335,14 +2346,14 @@ typeConstraint:
        | "enum" ->
            let _ltm, _gtm, args, _commas, mWhole = $4
            SynTypeConstraint.WhereTyparIsEnum($1, args, unionRanges $1.Range mWhole)
-       | nm -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier(nm)) }
+       | nm -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier(nm + " (3)")) }
 
   | typar COLON IDENT
      { match $3 with
        | "comparison" -> SynTypeConstraint.WhereTyparIsComparable($1, lhs parseState)
        | "equality" -> SynTypeConstraint.WhereTyparIsEquatable($1, lhs parseState)
        | "unmanaged" -> SynTypeConstraint.WhereTyparIsUnmanaged($1, lhs parseState)
-       | nm -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier(nm)) }
+       | nm -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier(nm + " (4)")) }
 
   | appType
      { SynTypeConstraint.WhereSelfConstrained($1, lhs parseState) }
@@ -2827,6 +2838,13 @@ cType:
      { let m = lhs parseState
        SynType.App(SynType.LongIdent(SynLongIdent([ident("nativeptr", m)], [], [ Some(IdentTrivia.OriginalNotation "*") ])), None, [$1], [], None, true, m) }
 
+/*
+  | cType QMARK
+    { SynType.WithNull($1, false, lhs parseState) }
+*/
+  | cType WITHNULL__
+    { SynType.WithNull($1, false, lhs parseState) }
+
   | cType AMP
      { let m = lhs parseState
        SynType.App(SynType.LongIdent(SynLongIdent([ident("byref", m)], [], [ Some(IdentTrivia.OriginalNotation "&") ])), None, [$1], [], None, true, m) }
@@ -5536,8 +5554,19 @@ appTypeConPower:
     { $1 }
 
 appType:
+  | appType MAYBENULL__
+    { SynType.WithNull($1, true, lhs parseState) }
+
+  | appType WITHNULL__
+    { SynType.WithNull($1, false, lhs parseState) }
+
+/*
+  | appType QMARK
+    { SynType.WithNull($1, false, lhs parseState) }
+*/
+
   | appType arrayTypeSuffix
-      { SynType.Array($2, $1, lhs parseState) }
+      {  SynType.Array($2, $1, lhs parseState) }
 
   | appType HIGH_PRECEDENCE_BRACK_APP arrayTypeSuffix /* only HPA for "name[]" allowed here */
       { SynType.Array($3, $1, lhs parseState) }
@@ -5765,7 +5794,7 @@ atomType:
 
   | NULL
      { let m = rhs parseState 1
-       SynType.StaticConstant(SynConst.String(null, SynStringKind.Regular, m), m) }
+       SynType.StaticConstantNull(m) }
 
   | CONST atomicExpr
      { let e, _ = $2
diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf
index 68d321a7cdf..0c35b2fb1a1 100644
--- a/src/Compiler/xlf/FSComp.txt.cs.xlf
+++ b/src/Compiler/xlf/FSComp.txt.cs.xlf
@@ -92,6 +92,11 @@
         Použití incr z knihovny F# je zastaralé. Více informací: https://aka.ms/fsharp-refcell-ops. Změňte prosím například incr cell na cell.Value <- cell.Value + 1.
         
       
+      
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        
+      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Pokud typ používá atribut [<Sealed>] i [<AbstractClass>], znamená to, že je statický. Členové instance nejsou povoleni.
@@ -117,6 +122,11 @@
         Dostupná přetížení:\n{0}
         
       
+      
+        The constraints 'delegate' and 'comparison' are inconsistent
+        The constraints 'delegate' and 'comparison' are inconsistent
+        
+      
       
         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.
@@ -147,6 +157,11 @@
         Známý typ parametru: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         Argument na indexu {0} neodpovídá
@@ -157,6 +172,21 @@
         Argument {0} neodpovídá
         
       
+      
+        The constraints 'struct' and 'null' are inconsistent
+        The constraints 'struct' and 'null' are inconsistent
+        
+      
+      
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        
+      
+      
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        
+      
       
         All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n    {1}    \nThis branch returns a tuple of length {2} of type\n    {3}    \n
         Všechny větve výrazu if musí vracet hodnoty implicitně převoditelné na typ první větve, což je řazená kolekce členů o délce {0} typu\n    {1}    \nTato větev vrací řazenou kolekci členů o délce {2} typu\n    {3}    \n
@@ -177,6 +207,11 @@
         Atribut sestavení {0} odkazuje na navržené sestavení {1}, které se nedá načíst nebo neexistuje. Ohlášená výjimka: {2} – {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         additional type-directed conversions
         další převody orientované na typ
@@ -332,6 +367,11 @@
         nepovinný zprostředkovatel komunikace s možnou hodnotou null
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         Otevřít deklaraci typu
@@ -647,6 +687,11 @@
         Vytiskněte odvozená rozhraní všech kompilovaných souborů do přidružených souborů podpisu.
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Vymazat mezipaměť výsledků správce balíčků
@@ -957,6 +1002,11 @@
         Atributy nejde použít pro rozšíření typů.
         
       
+      
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        
+      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Tento výraz záznamu kopírování a aktualizace mění všechna pole typu záznamu '{0}'. Zvažte použití syntaxe konstrukce záznamu.
@@ -1102,6 +1152,11 @@
         Hodnota {0} není funkce a nepodporuje zápis indexu.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         Syntaxe expr1[expr2] je při použití jako argument nejednoznačná. Více informací: https://aka.ms/fsharp-index-notation. Pokud plánujete indexování nebo vytváření řezů, musíte použít expr1.[expr2] na pozici argumentu. Pokud voláte funkci s vícenásobnými curryfikovanými argumenty, přidejte mezi ně mezeru, třeba someFunction expr1 [expr2].
@@ -1167,6 +1222,11 @@
         Tento výraz implicitně převede typ {0} na typ {1}. Přečtěte si téma https://aka.ms/fsharp-implicit-convs.
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         SynType.Or is not permitted in this declaration
         SynType.Or není v této deklaraci povoleno
diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf
index ee52b662d1d..be02e5e8b23 100644
--- a/src/Compiler/xlf/FSComp.txt.de.xlf
+++ b/src/Compiler/xlf/FSComp.txt.de.xlf
@@ -92,6 +92,11 @@
         Die Verwendung von "incr" aus der F#-Bibliothek ist veraltet. Siehe https://aka.ms/fsharp-refcell-ops. Ändern Sie z. B. "incr cell" in "cell.Value <- cell.Value + 1".
         
       
+      
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        
+      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Wenn ein Typ sowohl das Attribute [<Sealed>] wie auch [<AbstractClass>] verwendet, bedeutet dies, dass er statisch ist. Let-Bindungen der Instanz sind nicht zulässig.
@@ -117,6 +122,11 @@
         Verfügbare Überladungen:\n{0}
         
       
+      
+        The constraints 'delegate' and 'comparison' are inconsistent
+        The constraints 'delegate' and 'comparison' are inconsistent
+        
+      
       
         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.
@@ -147,6 +157,11 @@
         Bekannter Typparameter: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         Das Argument bei Index {0} stimmt nicht überein.
@@ -157,6 +172,21 @@
         Das Argument "{0}" stimmt nicht überein.
         
       
+      
+        The constraints 'struct' and 'null' are inconsistent
+        The constraints 'struct' and 'null' are inconsistent
+        
+      
+      
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        
+      
+      
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        
+      
       
         All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n    {1}    \nThis branch returns a tuple of length {2} of type\n    {3}    \n
         Alle Verzweigungen eines „If-Ausdrucks“ müssen Werte zurückgeben, die implizit in den Typ der ersten Verzweigung konvertierbar sind. In diesem Fall handelt es sich dabei um ein Tupel der Länge {0} des Typs.\n    {1}    \nDiese Verzweigung gibt ein Tupel der Länge {2} des Typs\n    {3}    \nzurück.
@@ -177,6 +207,11 @@
         Das Assemblyattribut "{0}" verweist auf eine Designerassembly "{1}", die entweder nicht geladen werden kann oder nicht vorhanden ist. Gemeldete Ausnahme: {2} – {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         additional type-directed conversions
         zusätzliche typgesteuerte Konvertierungen
@@ -332,6 +367,11 @@
         Interop, NULL-Werte zulassend, optional
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         Deklaration für offene Typen
@@ -647,6 +687,11 @@
         Drucken der abgeleiteten Schnittstellen aller Dateien an zugehörige Signaturdateien
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Löschen Sie den Ergebniscache des Paketmanagers
@@ -957,6 +1002,11 @@
         Attribute können nicht auf Typerweiterungen angewendet werden.
         
       
+      
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        
+      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Dieser Ausdruck zum Kopieren und Aktualisieren von Datensätzen ändert alle Felder des Datensatztyps "{0}". Erwägen Sie stattdessen die Verwendung der Datensatzerstellungssyntax.
@@ -1102,6 +1152,11 @@
         Der Wert "{0}" ist keine Funktion und unterstützt keine Indexnotation.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         Die Syntax "expr1[expr2]" ist mehrdeutig, wenn sie als Argument verwendet wird. Siehe https://aka.ms/fsharp-index-notation. Wenn Sie indizieren oder aufteilen möchten, müssen Sie "expr1.[expr2]' in Argumentposition verwenden. Wenn Sie eine Funktion mit mehreren geschweiften Argumenten aufrufen, fügen Sie ein Leerzeichen dazwischen hinzu, z. B. "someFunction expr1 [expr2]".
@@ -1167,6 +1222,11 @@
         Dieser Ausdruck konvertiert den Typ "{0}" implizit in den Typ "{1}". Siehe https://aka.ms/fsharp-implicit-convs.
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         SynType.Or is not permitted in this declaration
         SynType.Or ist in dieser Deklaration nicht zulässig.
diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf
index 9748064eb19..b840c9cf4f3 100644
--- a/src/Compiler/xlf/FSComp.txt.es.xlf
+++ b/src/Compiler/xlf/FSComp.txt.es.xlf
@@ -92,6 +92,11 @@
         El uso de "incr" de la biblioteca de F# está en desuso. Vea https://aka.ms/fsharp-refcell-ops. Por ejemplo, cambie "incr cell" a "cell.Value <- cell.Value + 1".
         
       
+      
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        
+      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Si un tipo utiliza ambos atributos [<Sealed>] y [<AbstractClass>], significa que es estático. No se permiten los enlaces let de instancia.
@@ -117,6 +122,11 @@
         Sobrecargas disponibles:\n{0}
         
       
+      
+        The constraints 'delegate' and 'comparison' are inconsistent
+        The constraints 'delegate' and 'comparison' are inconsistent
+        
+      
       
         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.
@@ -147,6 +157,11 @@
         Parámetro de tipo conocido: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         El argumento del índice {0} no coincide.
@@ -157,6 +172,21 @@
         El argumento "{0}" no coincide.
         
       
+      
+        The constraints 'struct' and 'null' are inconsistent
+        The constraints 'struct' and 'null' are inconsistent
+        
+      
+      
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        
+      
+      
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        
+      
       
         All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n    {1}    \nThis branch returns a tuple of length {2} of type\n    {3}    \n
         Todas las ramas de una expresión 'if' deben devolver valores implícitamente convertibles al tipo de la primera rama, que aquí es una tupla de longitud {0} de tipo\n    {1}    \nEsta rama devuelve una tupla de longitud {2} de tipo\n    {3}    \n
@@ -177,6 +207,11 @@
         El atributo de ensamblado "{0}" hace referencia a un ensamblado de diseñador "{1}" que no se puede cargar o no existe. Se notificó la excepción: {2} - {3}.
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         additional type-directed conversions
         conversiones adicionales dirigidas a tipos
@@ -332,6 +367,11 @@
         interoperabilidad opcional que admite valores NULL
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         declaración de tipo abierto
@@ -647,6 +687,11 @@
         Imprimir las interfaces deducidas de todos los archivos de compilación en los archivos de signatura asociados
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Borrar la caché de resultados del administrador de paquetes
@@ -957,6 +1002,11 @@
         Los atributos no se pueden aplicar a las extensiones de tipo.
         
       
+      
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        
+      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Esta expresión de copia y actualización de registros cambia todos los campos de tipo de registro "{0}". Es preferible utilizar la sintaxis de construcción de registros.
@@ -1102,6 +1152,11 @@
         El valor "{0}" no es una función y no admite la notación de índices.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         La sintaxis "expr1[expr2]" es ambigua cuando se usa como argumento. Vea https://aka.ms/fsharp-index-notation. Si piensa indexar o segmentar, debe usar "expr1.[expr2]" en la posición del argumento. Si se llama a una función con varios argumentos currificados, se agregará un espacio entre ellos, por ejemplo, "unaFunción expr1 [expr2]".
@@ -1167,6 +1222,11 @@
         Esta expresión convierte implícitamente el tipo '{0}' al tipo '{1}'. Consulte https://aka.ms/fsharp-implicit-convs.
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         SynType.Or is not permitted in this declaration
         SynType.Or no se permite en esta declaración
diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf
index d0eb8a412f3..e7ffcb0e4c1 100644
--- a/src/Compiler/xlf/FSComp.txt.fr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.fr.xlf
@@ -92,6 +92,11 @@
         L’utilisation de « incr » à partir de la bibliothèque F# est déconseillée. Voir https://aka.ms/fsharp-refcell-ops. Par exemple, veuillez remplacer « incr cell » par « cell.Value <- cell.Value + 1 ».
         
       
+      
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        
+      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Si un type utilise à la fois les attributs [<Sealed>] et [<AbstractClass>], cela signifie qu'il est statique. Les liaisons let d'instance ne sont pas autorisées.
@@ -117,6 +122,11 @@
         Surcharges disponibles :\n{0}
         
       
+      
+        The constraints 'delegate' and 'comparison' are inconsistent
+        The constraints 'delegate' and 'comparison' are inconsistent
+        
+      
       
         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.
@@ -147,6 +157,11 @@
         Paramètre de type connu : {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         L'argument à l'index {0} ne correspond pas
@@ -157,6 +172,21 @@
         L'argument '{0}' ne correspond pas
         
       
+      
+        The constraints 'struct' and 'null' are inconsistent
+        The constraints 'struct' and 'null' are inconsistent
+        
+      
+      
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        
+      
+      
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        
+      
       
         All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n    {1}    \nThis branch returns a tuple of length {2} of type\n    {3}    \n
         Toutes les branches d’une expression « if » doivent retourner des valeurs implicitement convertibles au type de la première branche, qui est ici un tuple de longueur {0} de type\n    {1}    \nCette branche renvoie un tuple de longueur {2} de type\n    {3}    \n
@@ -177,6 +207,11 @@
         L'attribut d'assembly '{0}' fait référence à un assembly de concepteur '{1}' qui ne peut pas être chargé ou qui n'existe pas. Exception signalée : {2} - {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         additional type-directed conversions
         conversions supplémentaires dirigées vers le type
@@ -332,6 +367,11 @@
         interopérabilité facultative pouvant accepter une valeur null
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         déclaration de type ouverte
@@ -647,6 +687,11 @@
         Imprimer les interfaces inférées de tous les fichiers de compilation sur les fichiers de signature associés
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Effacer le cache des résultats du Gestionnaire de package
@@ -957,6 +1002,11 @@
         Impossible d'appliquer des attributs aux extensions de type.
         
       
+      
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        
+      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Cette expression d'enregistrement de copie et de mise à jour modifie tous les champs du type d'enregistrement '{0}'. Envisagez d'utiliser la syntaxe de construction d'enregistrement à la place.
@@ -1102,6 +1152,11 @@
         La valeur « {0} » n’est pas une fonction et ne prend pas en charge la notation d’index.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         La syntaxe « expr1[expr2] » est ambiguë lorsqu’elle est utilisée comme argument. Voir https://aka.ms/fsharp-index-notation. Si vous avez l’intention d’indexer ou de découper, vous devez utiliser « expr1.[expr2] » en position d’argument. Si vous appelez une fonction avec plusieurs arguments codés, ajoutez un espace entre eux, par exemple « someFunction expr1 [expr2] ».
@@ -1167,6 +1222,11 @@
         Cette expression convertit implicitement le type « {0} » en type « {1} ». Voir https://aka.ms/fsharp-implicit-convs.
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         SynType.Or is not permitted in this declaration
         SynType.Or n’est pas autorisé dans cette déclaration
diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf
index a1c4c79cf5a..ec86e99587b 100644
--- a/src/Compiler/xlf/FSComp.txt.it.xlf
+++ b/src/Compiler/xlf/FSComp.txt.it.xlf
@@ -92,6 +92,11 @@
         L'uso di 'incr' dalla libreria F # è deprecato. Vedere https://aka.ms/fsharp-refcell-ops. Ad esempio, modificare 'incr cell' in 'cell.Value <- cell.Value + 1'.
         
       
+      
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        
+      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Se un tipo usa entrambi gli attributi [<Sealed>] e [<AbstractClass>], significa che è statico. Non sono consentite associazioni let delle istanze.
@@ -117,6 +122,11 @@
         Overload disponibili:\n{0}
         
       
+      
+        The constraints 'delegate' and 'comparison' are inconsistent
+        The constraints 'delegate' and 'comparison' are inconsistent
+        
+      
       
         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.
@@ -147,6 +157,11 @@
         Parametro di tipo noto: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         L'argomento alla posizione di indice {0} non corrisponde
@@ -157,6 +172,21 @@
         L'argomento '{0}' non corrisponde
         
       
+      
+        The constraints 'struct' and 'null' are inconsistent
+        The constraints 'struct' and 'null' are inconsistent
+        
+      
+      
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        
+      
+      
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        
+      
       
         All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n    {1}    \nThis branch returns a tuple of length {2} of type\n    {3}    \n
         Tutti i rami di un'espressione 'if' devono restituire valori convertibili in modo implicito nel tipo del primo ramo, che è una tupla di lunghezza {0} di tipo\n    {1}     \nQuesto ramo restituisce una tupla di lunghezza {2} di tipo\n    {3} \n
@@ -177,6 +207,11 @@
         L'attributo di assembly '{0}' fa riferimento a un assembly '{1}' della finestra di progettazione che non è stato caricato o non esiste. L'eccezione restituita è {2} - {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         additional type-directed conversions
         conversioni aggiuntive dirette ai tipi
@@ -332,6 +367,11 @@
         Interop facoltativo nullable
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         dichiarazione di tipo aperto
@@ -647,6 +687,11 @@
         Stampare le interfacce derivate di tutti i file di compilazione nei file di firma associati
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Cancellare la cache dei risultati di Gestione pacchetti
@@ -957,6 +1002,11 @@
         Gli attributi non possono essere applicati a estensioni di tipo.
         
       
+      
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        
+      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Questa espressione di record di copia e aggiornamento modifica tutti i campi del tipo di record '{0}'. Provare a usare la sintassi di costruzione dei record.
@@ -1102,6 +1152,11 @@
         Questo valore '{0}' non è una funzione e non supporta la notazione degli indici.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         La sintassi 'expr1[expr2]' è ambigua se usata come argomento. Vedere https://aka.ms/fsharp-index-notation. Se si intende eseguire l'indicizzazione o il sezionamento, è necessario usare 'expr1.[expr2]' nella posizione dell'argomento. Se si chiama una funzione con più argomenti sottoposti a corsi, aggiungere uno spazio tra di essi, ad esempio 'someFunction expr1 [expr2]'.
@@ -1167,6 +1222,11 @@
         Questa espressione converte in modo implicito il tipo '{0}' nel tipo '{1}'. Vedere https://aka.ms/fsharp-implicit-convs.
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         SynType.Or is not permitted in this declaration
         SynType.Or non è consentito in questa dichiarazione
diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf
index a1e4157a4de..39416b6337c 100644
--- a/src/Compiler/xlf/FSComp.txt.ja.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ja.xlf
@@ -92,6 +92,11 @@
         F# ライブラリからの 'incr' の使用は非推奨です。https://aka.ms/fsharp-refcell-ops を参照してください。たとえば、'incr cell' を 'cell.Value <- cell.Value +1' に変更してください。
         
       
+      
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        
+      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         型が [<Sealed>] と [<AbstractClass>] の両方の属性を使用する場合、それは静的であることを意味します。インスタンス let バインドは許可されません。
@@ -117,6 +122,11 @@
         使用可能なオーバーロード:\n{0}
         
       
+      
+        The constraints 'delegate' and 'comparison' are inconsistent
+        The constraints 'delegate' and 'comparison' are inconsistent
+        
+      
       
         A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation.
         ジェネリック コンストラクトでは、ジェネリック型パラメーターが構造体または参照型として認識されている必要があります。型の注釈の追加を検討してください。
@@ -147,6 +157,11 @@
         既知の型パラメーター: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         インデックス {0} の引数が一致しません
@@ -157,6 +172,21 @@
         引数 '{0}' が一致しません
         
       
+      
+        The constraints 'struct' and 'null' are inconsistent
+        The constraints 'struct' and 'null' are inconsistent
+        
+      
+      
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        
+      
+      
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        
+      
       
         All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n    {1}    \nThis branch returns a tuple of length {2} of type\n    {3}    \n
         'if' 式のすべての分岐は、最初の分岐の型に暗黙的に変換できる値を返す必要があります。これは、型の長さ {0} のタプルです\n    {1}    \nこの分岐は、型の長さ {2} のタプルを返します\n    {3}    \n
@@ -177,6 +207,11 @@
         アセンブリ属性 '{0}' は、デザイナー アセンブリ '{1}' を参照していますが、これは読み込むことができないか、存在していません。報告された例外: {2} - {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         additional type-directed conversions
         その他の型指定された変換
@@ -332,6 +367,11 @@
         Null 許容のオプションの相互運用
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         オープン型宣言
@@ -647,6 +687,11 @@
         すべてのコンパイル ファイルの推定されたインターフェイスを関連する署名ファイルに印刷します
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         パッケージ マネージャーの結果キャッシュをクリアする
@@ -957,6 +1002,11 @@
         属性を型拡張に適用することはできません。
         
       
+      
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        
+      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         この copy-and-update レコード式は、レコードの種類が '{0}' であるすべてのフィールドを変更します。代わりにレコード構築構文を使用することを検討してください。
@@ -1102,6 +1152,11 @@
         値 '{0}' は関数ではなく、インデックス表記をサポートしていません。
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         構文 'expr1[expr2]' は引数として使用されている場合、あいまいです。https://aka.ms/fsharp-index-notation を参照してください。インデックス作成またはスライスを行う場合は、'expr1.[expr2]' を引数の位置に使用する必要があります。複数のカリー化された引数を持つ関数を呼び出す場合は、'expr1 [expr2]' のように間にスペースを追加します。
@@ -1167,6 +1222,11 @@
         この式は、型 '{0}' を型 '{1}' に暗黙的に変換します。https://aka.ms/fsharp-implicit-convs を参照してください。
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         SynType.Or is not permitted in this declaration
         SynType.Or はこの宣言では許可されていません
diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf
index 7c4f481d2a2..607b67baaed 100644
--- a/src/Compiler/xlf/FSComp.txt.ko.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ko.xlf
@@ -92,6 +92,11 @@
         F# 라이브러리의 'incr' 사용은 더 이상 사용되지 않습니다. https://aka.ms/fsharp-refcell-ops를 참조하세요. 예를 들어 'incr cell'을 'cell.Value <- cell.Value + 1'로 변경하세요.
         
       
+      
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        
+      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         형식이 [<Sealed>] 및 [<AbstractClass>] 특성을 모두 사용하는 경우 정적임을 의미합니다. 인스턴스 let 바인딩은 허용되지 않습니다.
@@ -117,6 +122,11 @@
         사용 가능한 오버로드:\n{0}
         
       
+      
+        The constraints 'delegate' and 'comparison' are inconsistent
+        The constraints 'delegate' and 'comparison' are inconsistent
+        
+      
       
         A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation.
         제네릭 구문을 사용하려면 구조체 또는 참조 형식의 제네릭 형식 매개 변수가 필요합니다. 형식 주석을 추가하세요.
@@ -147,6 +157,11 @@
         알려진 형식 매개 변수: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         인덱스 {0}의 인수가 일치하지 않습니다.
@@ -157,6 +172,21 @@
         '{0}' 인수가 일치하지 않습니다.
         
       
+      
+        The constraints 'struct' and 'null' are inconsistent
+        The constraints 'struct' and 'null' are inconsistent
+        
+      
+      
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        
+      
+      
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        
+      
       
         All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n    {1}    \nThis branch returns a tuple of length {2} of type\n    {3}    \n
         'if' 식의 모든 분기는 첫 번째 분기의 유형으로 암시적으로 변환 가능한 값을 반환해야 합니다. 여기서는 형식이 \n    {1}이고 길이가 {0}인 튜플입니다.    \n이 분기는 형식이 \n    {3}이고 길이가 {2}인 튜플을 반환합니다.    \n
@@ -177,6 +207,11 @@
         '{0}' 어셈블리 특성이 로드할 수 없거나 존재하지 않는 디자이너 어셈블리'{1}'을(를) 참조합니다. 보고된 예외: {2} - {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         additional type-directed conversions
         추가 형식-디렉션 변환
@@ -332,6 +367,11 @@
         nullable 선택적 interop
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         개방형 형식 선언
@@ -647,6 +687,11 @@
         모든 컴파일 파일의 유추된 인터페이스를 관련 서명 파일로 인쇄합니다.
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         패키지 관리자 결과 캐시 지우기
@@ -957,6 +1002,11 @@
         형식 확장에 특성을 적용할 수 없습니다.
         
       
+      
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        
+      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         이 레코드 복사 및 업데이트 식은 '{0}' 레코드 형식의 모든 필드를 변경합니다. 레코드 생성 구문을 대신 사용하는 것이 좋습니다.
@@ -1102,6 +1152,11 @@
         '{0}' 값은 함수가 아니며 인덱스 표기법을 지원하지 않습니다.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         'expr1[expr2]' 구문은 인수로 사용될 때 모호합니다. https://aka.ms/fsharp-index-notation을 참조하세요. 인덱싱이나 슬라이싱을 하려면 인수 위치에 'expr1.[expr2]'를 사용해야 합니다. 여러 개의 커리된 인수로 함수를 호출하는 경우 그 사이에 공백을 추가하세요(예: 'someFunction expr1 [expr2]').
@@ -1167,6 +1222,11 @@
         이 식은 암시적으로 '{0}' 형식을 '{1}' 형식으로 변환 합니다. https://aka.ms/fsharp-implicit-convs 참조
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         SynType.Or is not permitted in this declaration
         SynType.Or는 이 선언에서 허용되지 않습니다.
diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf
index cea66cde2e9..f33dd980b7d 100644
--- a/src/Compiler/xlf/FSComp.txt.pl.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pl.xlf
@@ -92,6 +92,11 @@
         Użycie elementu „incr” z biblioteki języka F# jest przestarzałe. Sprawdź stronę https://aka.ms/fsharp-refcell-ops. Na przykład zmień wyrażenie „incr cell” na „cell.Value <- cell.Value + 1”.
         
       
+      
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        
+      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Jeśli typ używa obu atrybutów [<Sealed>] i [< AbstractClass>], oznacza to, że jest on statyczny. Połączenia let wystąpienia są niedozwolone.
@@ -117,6 +122,11 @@
         Dostępne przeciążenia:\n{0}
         
       
+      
+        The constraints 'delegate' and 'comparison' are inconsistent
+        The constraints 'delegate' and 'comparison' are inconsistent
+        
+      
       
         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.
@@ -147,6 +157,11 @@
         Parametr znanego typu: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         Argument pod indeksem {0} nie jest zgodny
@@ -157,6 +172,21 @@
         Argument „{0}” nie jest zgodny
         
       
+      
+        The constraints 'struct' and 'null' are inconsistent
+        The constraints 'struct' and 'null' are inconsistent
+        
+      
+      
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        
+      
+      
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        
+      
       
         All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n    {1}    \nThis branch returns a tuple of length {2} of type\n    {3}    \n
         Wszystkie gałęzie wyrażenia „if” muszą zwracać wartości niejawnie konwertowalne na typ pierwszej gałęzi, która tutaj jest krotką o długości {0} typu\n    {1}    \nTa gałąź zwraca krotkę o długości {2} typu\n    {3}    \n
@@ -177,6 +207,11 @@
         Atrybut zestawu „{0}” odwołuje się do zestawu projektanta „{1}”, którego nie można załadować lub który nie istnieje. Zgłoszony wyjątek: {2} — {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         additional type-directed conversions
         dodatkowe konwersje ukierunkowane na typ
@@ -332,6 +367,11 @@
         opcjonalna międzyoperacyjność dopuszczająca wartość null
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         deklaracja typu otwartego
@@ -647,6 +687,11 @@
         Drukowanie wywnioskowanych interfejsów wszystkich plików kompilacji do skojarzonych plików sygnatur
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Wyczyść pamięć podręczną wyników menedżera pakietów
@@ -957,6 +1002,11 @@
         Atrybutów nie można stosować do rozszerzeń typu.
         
       
+      
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        
+      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         To wyrażenie rekordu kopiowania i aktualizacji zmienia wszystkie pola typu rekordu „{0}”. Zamiast tego rozważ użycie składni konstrukcji rekordu.
@@ -1102,6 +1152,11 @@
         Wartość elementu „{0}” nie jest funkcją i nie obsługuje notacji indeksowej.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         Składnia wyrażenia „expr1[expr2]” jest niejednoznaczna, gdy jest używana jako argument. Zobacz https://aka.ms/fsharp-index-notation. Jeśli zamierzasz indeksować lub fragmentować, to w pozycji argumentu musi być użyte wyrażenie „expr1.[expr2]”. Jeśli wywołujesz funkcję z wieloma argumentami typu curried, dodaj spację między nimi, np. „someFunction expr1 [expr2]”.
@@ -1167,6 +1222,11 @@
         To wyrażenie bezwzględnie konwertuje typ "{0}" na typ "{1}". Zobacz https://aka.ms/fsharp-implicit-convs.
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         SynType.Or is not permitted in this declaration
         Element SynType.Or nie jest dozwolony w tej deklaracji
diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
index 79c864480fd..f7a8891e84d 100644
--- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
@@ -92,6 +92,11 @@
         O uso de 'incr' da biblioteca F# foi preterido. Consulte https://aka.ms/fsharp-refcell-ops. Por exemplo, altere a célula 'incr cell' para 'cell.Value <- cell.Value + 1'.
         
       
+      
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        
+      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Se um tipo usar os atributos [<Sealed>] e [<AbstractClass>], isso significará que ele é estático. Associações de permissão de instância não são permitidas.
@@ -117,6 +122,11 @@
         Sobrecargas disponíveis:\n{0}
         
       
+      
+        The constraints 'delegate' and 'comparison' are inconsistent
+        The constraints 'delegate' and 'comparison' are inconsistent
+        
+      
       
         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.
@@ -147,6 +157,11 @@
         Parâmetro de tipo conhecido: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         O argumento no índice {0} não corresponde
@@ -157,6 +172,21 @@
         O argumento '{0}' não corresponde
         
       
+      
+        The constraints 'struct' and 'null' are inconsistent
+        The constraints 'struct' and 'null' are inconsistent
+        
+      
+      
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        
+      
+      
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        
+      
       
         All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n    {1}    \nThis branch returns a tuple of length {2} of type\n    {3}    \n
         Todas as ramificações de uma expressão 'if' devem retornar valores implicitamente conversíveis ao tipo da primeira ramificação, que aqui é uma tupla de comprimento {0} do tipo\n    {1}    \nEsta ramificação retorna uma tupla de comprimento {2} do tipo\n    {3}    \n
@@ -177,6 +207,11 @@
         O atributo de assembly '{0}' refere-se a um assembly de designer '{1}' que não pode ser carregado ou que não existe. A exceção relatada foi {2} – {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         additional type-directed conversions
         conversões direcionadas por tipos adicionais
@@ -332,6 +367,11 @@
         interoperabilidade opcional anulável
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         declaração de tipo aberto
@@ -647,6 +687,11 @@
         Imprimir as interfaces inferidas de todos os arquivos de compilação para os arquivos de assinatura associados
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Limpar o cache de resultados do gerenciador de pacotes
@@ -957,6 +1002,11 @@
         Os atributos não podem ser aplicados às extensões de tipo.
         
       
+      
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        
+      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Essa expressão de registro copiar e atualizar altera todos os campos do tipo de registro '{0}'. Considere usar a sintaxe de construção de registro em vez disso.
@@ -1102,6 +1152,11 @@
         O valor '{0}' não é uma função e não dá suporte à notação de índice.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         A sintaxe '[expr1][expr2]' é ambígua quando usada como um argumento. Consulte https://aka.ms/fsharp-index-notation. Se você pretende indexar ou colocar em fatias, deve usar '(expr1).[expr2]' na posição do argumento. Se chamar uma função com vários argumentos na forma curried, adicione um espaço entre eles, por exemplo, 'someFunction [expr1] [expr2]'.
@@ -1167,6 +1222,11 @@
         Essa expressão converte implicitamente o tipo '{0}' ao tipo '{1}'. Consulte https://aka.ms/fsharp-implicit-convs.
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         SynType.Or is not permitted in this declaration
         SynType.Or não é permitido nesta declaração
diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf
index 831c7891388..4e75473322b 100644
--- a/src/Compiler/xlf/FSComp.txt.ru.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ru.xlf
@@ -92,6 +92,11 @@
         Использование "incr" из библиотеки F# является нерекомендуемым. См. https://aka.ms/fsharp-refcell-ops. Например, замените "incr cell" на "cell.Value <- cell.Value + 1".
         
       
+      
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        
+      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Если тип использует оба атрибута [<Sealed>] и [<AbstractClass>], это означает, что он статический. Привязки экземпляра let не разрешены.
@@ -117,6 +122,11 @@
         Доступные перегрузки:\n{0}
         
       
+      
+        The constraints 'delegate' and 'comparison' are inconsistent
+        The constraints 'delegate' and 'comparison' are inconsistent
+        
+      
       
         A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation.
         В универсальной конструкции требуется использовать параметр универсального типа, известный как структура или ссылочный тип. Рекомендуется добавить заметку с типом.
@@ -147,6 +157,11 @@
         Известный параметр типа: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         Аргумент в индексе {0} не соответствует
@@ -157,6 +172,21 @@
         Аргумент "{0}" не соответствует
         
       
+      
+        The constraints 'struct' and 'null' are inconsistent
+        The constraints 'struct' and 'null' are inconsistent
+        
+      
+      
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        
+      
+      
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        
+      
       
         All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n    {1}    \nThis branch returns a tuple of length {2} of type\n    {3}    \n
         Все ветви выражения "if" должны возвращать значения, поддерживающие неявное преобразование в тип первой ветви, которым здесь является кортеж длиной {0} типа\n    {1}    \nЭта ветвь возвращает кортеж длиной {2} типа\n    {3}    \n
@@ -177,6 +207,11 @@
         Атрибут сборки "{0}" ссылается на сборку конструктора "{1}", которая не может быть загружена или не существует. Получено исключение: {2} — {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         additional type-directed conversions
         дополнительные преобразования на основе типа
@@ -332,6 +367,11 @@
         необязательное взаимодействие, допускающее значение NULL
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         объявление открытого типа
@@ -647,6 +687,11 @@
         Печать определяемых интерфейсов всех файлов компиляции в связанные файлы подписей
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Очистка кэша результатов диспетчера пакетов
@@ -957,6 +1002,11 @@
         Атрибуты не могут быть применены к расширениям типа.
         
       
+      
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        
+      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Это выражение записи копирования и обновления изменяет все поля типа записи "{0}". Вместо этого можно использовать синтаксис конструкции записи.
@@ -1102,6 +1152,11 @@
         Значение {0} не является функцией и не поддерживает нотацию индекса.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         Синтаксис "expr1[expr2]" неоднозначен при использовании в качестве аргумента. См. https://aka.ms/fsharp-index-notation. Если вы намереваетесь индексировать или разрезать, необходимо использовать "expr1.[expr2]" в позиции аргумента. При вызове функции с несколькими каррированными аргументами добавьте пробел между ними, например "someFunction expr1 [expr2]".
@@ -1167,6 +1222,11 @@
         Это выражение неявно преобразует тип "{0}" в тип "{1}". См. сведения на странице https://aka.ms/fsharp-implicit-convs.
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         SynType.Or is not permitted in this declaration
         SynType.Or не допускается в этом объявлении
diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf
index 9e455903428..4d8e47af9a0 100644
--- a/src/Compiler/xlf/FSComp.txt.tr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.tr.xlf
@@ -92,6 +92,11 @@
         F# kitaplığından gelen 'incr' kullanımı kullanım dışı. https://aka.ms/fsharp-refcell-ops’a bakın. Örneğin, lütfen 'incr cell' ifadesini 'cell.Value <- cell.Value + 1' olarak değiştirin.
         
       
+      
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        
+      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Bir tür, hem [<Sealed>] hem de [< AbstractClass>] özniteliklerini kullanıyorsa bu statik olduğu anlamına gelir. Örnek let bağlamalarına izin verilmez.
@@ -117,6 +122,11 @@
         Kullanılabilir aşırı yüklemeler:\n{0}
         
       
+      
+        The constraints 'delegate' and 'comparison' are inconsistent
+        The constraints 'delegate' and 'comparison' are inconsistent
+        
+      
       
         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.
@@ -147,6 +157,11 @@
         Bilinen tür parametresi: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         {0} dizinindeki bağımsız değişken eşleşmiyor
@@ -157,6 +172,21 @@
         '{0}' bağımsız değişkeni eşleşmiyor
         
       
+      
+        The constraints 'struct' and 'null' are inconsistent
+        The constraints 'struct' and 'null' are inconsistent
+        
+      
+      
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        
+      
+      
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        
+      
       
         All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n    {1}    \nThis branch returns a tuple of length {2} of type\n    {3}    \n
         Bir 'if' ifadesinin tüm dalları, örtük olarak ilk dalın türüne dönüştürülebilir değerler döndürmelidir. Burada ilk dal {0} uzunluğunda türü\n    {1} olan bir demet    \nBu dal {2} uzunluğunda türü\n    {3}    \nolan bir demet döndürüyor
@@ -177,6 +207,11 @@
         '{0}' bütünleştirilmiş kod özniteliği, yüklenemeyen veya mevcut olmayan '{1}' tasarımcı bütünleştirilmiş koduna başvuruyor. Bildirilen özel durum: {2} - {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         additional type-directed conversions
         ek tür ile yönlendirilen dönüştürmeler
@@ -332,6 +367,11 @@
         null atanabilir isteğe bağlı birlikte çalışma
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         açık tür bildirimi
@@ -647,6 +687,11 @@
         Tüm derleme dosyalarının çıkarsanan arabirimlerini ilişkili imza dosyalarına yazdır
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Paket yöneticisi sonuçları önbelleğini temizle
@@ -957,6 +1002,11 @@
         Öznitelikler tür uzantılarına uygulanamaz.
         
       
+      
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        
+      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Bu kopyalama ve güncelleştirme kayıt ifadesi, '{0}' kayıt türündeki tüm alanları değiştirir. Bunun yerine kayıt oluşturma söz dizimini kullanmayı deneyin.
@@ -1102,6 +1152,11 @@
         “{0}” değeri bir işlev değildir ve dizin gösterimini desteklemez.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         Söz dizimi “expr1[expr2]” artık dizin oluşturma için ayrılmıştır ve bağımsız değişken olarak kullanıldığında belirsizdir. https://aka.ms/fsharp-index-notation'a bakın. Dizin oluşturmayı veya dilimlemeyi düşünüyorsanız, bağımsız değişken konumunda “expr1.[expr2]” kullanmalısınız. Birden çok curry bağımsız değişkenli bir işlev çağırıyorsanız, aralarına bir boşluk ekleyin, örn. “someFunction expr1 [expr2]”.
@@ -1167,6 +1222,11 @@
         Bu ifade '{0}' türünü örtülü olarak '{1}' türüne dönüştürür. https://aka.ms/fsharp-implicit-convs adresine bakın.
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         SynType.Or is not permitted in this declaration
         Bu bildirimde SynType.Or'a izin verilmiyor
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
index 8338b0da896..6a537df75ee 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
@@ -92,6 +92,11 @@
         已弃用 F# 库中的“incr”。请参阅 https://aka.ms/fsharp-refcell-ops。 例如,请将“incr cell”更改为“cell.Value <- cell.Value + 1”。
         
       
+      
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        
+      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         如果类型同时使用 [<Sealed>] 和 [<AbstractClass>] 属性,则表示它是静态的。不允许使用实例允许绑定。
@@ -117,6 +122,11 @@
         可用重载:\n{0}
         
       
+      
+        The constraints 'delegate' and 'comparison' are inconsistent
+        The constraints 'delegate' and 'comparison' are inconsistent
+        
+      
       
         A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation.
         泛型构造要求泛型类型参数被视为结构或引用类型。请考虑添加类型注释。
@@ -147,6 +157,11 @@
         已知类型参数: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         索引 {0} 处的参数不匹配
@@ -157,6 +172,21 @@
         参数 "{0}" 不匹配
         
       
+      
+        The constraints 'struct' and 'null' are inconsistent
+        The constraints 'struct' and 'null' are inconsistent
+        
+      
+      
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        
+      
+      
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        
+      
       
         All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n    {1}    \nThis branch returns a tuple of length {2} of type\n    {3}    \n
         “if” 表达式的所有分支必须返回可隐式转换为第一个分支类型的值,这是一个长度为 {0} 的类型的元组\n    {1}    \n此分支会返回长度为 {2} 的类型的元组\n    {3}    \n
@@ -177,6 +207,11 @@
         程序集属性“{0}”引用了无法加载或不存在的设计器程序集“{1}”。报告的异常是: {2} - {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         additional type-directed conversions
         附加类型定向转换
@@ -332,6 +367,11 @@
         可以为 null 的可选互操作
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         开放类型声明
@@ -647,6 +687,11 @@
         将所有编译文件的推断接口打印到关联的签名文件
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         清除包管理器结果缓存
@@ -957,6 +1002,11 @@
         属性不可应用于类型扩展。
         
       
+      
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        
+      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         此复制和更新记录表达式更改记录类型“{0}”的所有字段。请考虑改用记录构造语法。
@@ -1102,6 +1152,11 @@
         值 '{0}' 不是函数,不支持索引表示法。
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         语法“expr1[expr2]”用作参数时不明确。请参阅 https://aka.ms/fsharp-index-notation。如果要索引或切片,则必须在参数位置使用“expr1.[expr2]”。如果使用多个扩充参数调用函数,请在它们之间添加空格,例如“someFunction expr1 [expr2]”。
@@ -1167,6 +1222,11 @@
         此表达式将类型“{0}”隐式转换为类型“{1}”。请参阅 https://aka.ms/fsharp-implicit-convs。
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         SynType.Or is not permitted in this declaration
         此声明中不允许使用 SynType.Or
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
index 5fbdf0f332c..7fd1a1098fe 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
@@ -92,6 +92,11 @@
         透過 F# 程式庫使用 'incr' 的方式已淘汰。請參閱 https://aka.ms/fsharp-refcell-ops。舉例來說,請將 'incr cell' 變更為 'cell.Value <- cell.Value + 1'。
         
       
+      
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
+        
+      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         如果類型同時使用 [<Sealed>] 和 [<AbstractClass>] 屬性,表示其為靜態。不允許執行個體 'let' 繫結。
@@ -117,6 +122,11 @@
         可用的多載:\n{0}
         
       
+      
+        The constraints 'delegate' and 'comparison' are inconsistent
+        The constraints 'delegate' and 'comparison' are inconsistent
+        
+      
       
         A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation.
         泛型建構要求泛型型別參數必須指定為結構或參考型別。請考慮新增型別註解。
@@ -147,6 +157,11 @@
         已知的型別參數: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         位於索引 {0} 的引數不相符
@@ -157,6 +172,21 @@
         引數 '{0}' 不相符
         
       
+      
+        The constraints 'struct' and 'null' are inconsistent
+        The constraints 'struct' and 'null' are inconsistent
+        
+      
+      
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        
+      
+      
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        
+      
       
         All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n    {1}    \nThis branch returns a tuple of length {2} of type\n    {3}    \n
         'if' 運算式的所有分支都傳回可隱含轉換為第一個分支的類型的值,這是類型為\n    {1}    \n的元組長度 {0}此分支傳回的是類型為\n    {3}    \n的元組長度 {2}
@@ -177,6 +207,11 @@
         無法載入組件屬性 '{0}' 參考的設計工具組件 '{1}' 或其不存在。回報的例外狀況: {2} - {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         additional type-directed conversions
         其他類型導向轉換
@@ -332,6 +367,11 @@
         可為 Null 的選擇性 Interop
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         開放式類型宣告
@@ -647,6 +687,11 @@
         將所有編譯檔案的推斷介面列印至相關聯的簽章檔案
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         清除封裝管理員結果快取
@@ -957,6 +1002,11 @@
         屬性無法套用到類型延伸模組。
         
       
+      
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
+        
+      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         此複製和更新記錄運算式將變更記錄類型為 '{0}' 的所有欄位。請考慮改用記錄建構語法。
@@ -1102,6 +1152,11 @@
         值 '{0}' 並非函式,不支援索引標記法。
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         語法 'expr1[expr2]' 用作引數時不明確。請參閱 https://aka.ms/fsharp-index-notation。如果您要編製索引或切割,則必須在引數位置使用 'expr1.[expr2]'。如果要呼叫具有多個調用引數的函式,請在它們之間新增空格,例如 'someFunction expr1 [expr2]'。
@@ -1167,6 +1222,11 @@
         此運算式將類型 '{0}' 隱含轉換為類型 '{1}'。請參閱 https://aka.ms/fsharp-implicit-convs。
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         SynType.Or is not permitted in this declaration
         此宣告中不允許 SynType.Or
diff --git a/src/Compiler/xlf/FSStrings.cs.xlf b/src/Compiler/xlf/FSStrings.cs.xlf
index 7ebb3c64f7c..3b399e8d46e 100644
--- a/src/Compiler/xlf/FSStrings.cs.xlf
+++ b/src/Compiler/xlf/FSStrings.cs.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support nullness.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Neshoda typů Očekává se řazená kolekce členů o délce {0} typu\n    {1}    \nale odevzdala se řazená kolekce členů o délce {2} typu\n    {3}{4}\n
@@ -42,6 +62,16 @@
         interpolovaný řetězec (část)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Viz taky {0}.
diff --git a/src/Compiler/xlf/FSStrings.de.xlf b/src/Compiler/xlf/FSStrings.de.xlf
index 69473239ef4..bd68a3675e3 100644
--- a/src/Compiler/xlf/FSStrings.de.xlf
+++ b/src/Compiler/xlf/FSStrings.de.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support nullness.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Typenkonflikt. Es wurde ein Tupel der Länge {0} des Typs\n    {1}    \nerwartet, aber ein Tupel der Länge {2} des Typs\n    {3}{4}\n angegeben.
@@ -42,6 +62,16 @@
         Interpolierte Zeichenfolge (Teil)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Siehe auch "{0}".
diff --git a/src/Compiler/xlf/FSStrings.es.xlf b/src/Compiler/xlf/FSStrings.es.xlf
index 2b06bc30aa3..2470385a990 100644
--- a/src/Compiler/xlf/FSStrings.es.xlf
+++ b/src/Compiler/xlf/FSStrings.es.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support nullness.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Error de coincidencia de tipos. Se espera una tupla de longitud {0} de tipo\n    {1}    \nperero se ha proporcionado una tupla de longitud {2} de tipo\n    {3}{4}\n
@@ -42,6 +62,16 @@
         cadena interpolada (parte)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Vea también {0}.
diff --git a/src/Compiler/xlf/FSStrings.fr.xlf b/src/Compiler/xlf/FSStrings.fr.xlf
index cce4c1059b0..ddc17e5c270 100644
--- a/src/Compiler/xlf/FSStrings.fr.xlf
+++ b/src/Compiler/xlf/FSStrings.fr.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support nullness.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Incompatibilité de type. Tuple de longueur attendu {0} de type\n {1} \nmais tuple de longueur {2} de type\n    {3}{4}\n
@@ -42,6 +62,16 @@
         chaîne interpolée (partie)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Voir aussi {0}.
diff --git a/src/Compiler/xlf/FSStrings.it.xlf b/src/Compiler/xlf/FSStrings.it.xlf
index f2f77ac5fee..e4845cfd12b 100644
--- a/src/Compiler/xlf/FSStrings.it.xlf
+++ b/src/Compiler/xlf/FSStrings.it.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support nullness.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Tipo non corrispondente. È prevista una tupla di lunghezza {0} di tipo\n   {1}    \n, ma è stata specificata una tupla di lunghezza {2} di tipo\n    {3}{4}\n
@@ -42,6 +62,16 @@
         stringa interpolata (parte)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Vedere anche {0}.
diff --git a/src/Compiler/xlf/FSStrings.ja.xlf b/src/Compiler/xlf/FSStrings.ja.xlf
index fec45d4eb05..5f49b8eb56b 100644
--- a/src/Compiler/xlf/FSStrings.ja.xlf
+++ b/src/Compiler/xlf/FSStrings.ja.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support nullness.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         型が一致しません。型の長さ {0} のタプルが必要です\n    {1}    \nただし、型の長さ {2} のタプルが指定された場合\n    {3}{4}\n
@@ -42,6 +62,16 @@
         補間された文字列 (部分)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         。{0} も参照してください。
diff --git a/src/Compiler/xlf/FSStrings.ko.xlf b/src/Compiler/xlf/FSStrings.ko.xlf
index c16c466ebc4..54a71c5fe12 100644
--- a/src/Compiler/xlf/FSStrings.ko.xlf
+++ b/src/Compiler/xlf/FSStrings.ko.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support nullness.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         유형 불일치. 형식이 \n    {1}이고 길이가 {0}인 튜플이 필요합니다.    \n그러나 형식이 \n    {3}이고 길이가 {2}인 튜플이 제공되었습니다.{4}\n
@@ -42,6 +62,16 @@
         보간 문자열(부분)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         {0}도 참조하세요.
diff --git a/src/Compiler/xlf/FSStrings.pl.xlf b/src/Compiler/xlf/FSStrings.pl.xlf
index 385be4e2a2a..6845eae60ce 100644
--- a/src/Compiler/xlf/FSStrings.pl.xlf
+++ b/src/Compiler/xlf/FSStrings.pl.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support nullness.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Niezgodność. Oczekiwano krotki o długości {0} typu\n    {1}    \nale otrzymano krotkę o długości {2} typu\n    {3}{4}\n
@@ -42,6 +62,16 @@
         ciąg interpolowany (część)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Zobacz też {0}.
diff --git a/src/Compiler/xlf/FSStrings.pt-BR.xlf b/src/Compiler/xlf/FSStrings.pt-BR.xlf
index 8fa1e1ee33d..f31a0882f77 100644
--- a/src/Compiler/xlf/FSStrings.pt-BR.xlf
+++ b/src/Compiler/xlf/FSStrings.pt-BR.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support nullness.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Tipo incompatível. Esperando uma tupla de comprimento {0} do tipo\n    {1}    \nmas recebeu uma tupla de comprimento {2} do tipo\n    {3}{4}\n
@@ -42,6 +62,16 @@
         cadeia de caracteres interpolada (parte)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Consulte também {0}.
diff --git a/src/Compiler/xlf/FSStrings.ru.xlf b/src/Compiler/xlf/FSStrings.ru.xlf
index 27b87f0c6b0..54fb0c052fd 100644
--- a/src/Compiler/xlf/FSStrings.ru.xlf
+++ b/src/Compiler/xlf/FSStrings.ru.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support nullness.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Несоответствие типов. Ожидается кортеж длиной {0} типа\n    {1},    \nно предоставлен кортеж длиной {2} типа\n    {3}{4}\n
@@ -42,6 +62,16 @@
         интерполированная строка (часть)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . См. также {0}.
diff --git a/src/Compiler/xlf/FSStrings.tr.xlf b/src/Compiler/xlf/FSStrings.tr.xlf
index fe1b018c46e..43d48a8ea73 100644
--- a/src/Compiler/xlf/FSStrings.tr.xlf
+++ b/src/Compiler/xlf/FSStrings.tr.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support nullness.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Tür uyuşmazlığı. {0} uzunluğunda türü\n {1} \nolan bir demet bekleniyordu ancak {2} uzunluğunda türü\n    {3}{4}\nolan bir demet verildi
@@ -42,6 +62,16 @@
         düz metin arasına kod eklenmiş dize (parça)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Ayrıca bkz. {0}.
diff --git a/src/Compiler/xlf/FSStrings.zh-Hans.xlf b/src/Compiler/xlf/FSStrings.zh-Hans.xlf
index 89cac4d4d7a..4bd02158e64 100644
--- a/src/Compiler/xlf/FSStrings.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSStrings.zh-Hans.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support nullness.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         类型不匹配。应为长度为 {0} 的类型的元组\n    {1}    \n但提供了长度为 {2} 的类型的元组\n    {3}{4}\n
@@ -42,6 +62,16 @@
         内插字符串(部分)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         。请参见 {0}。
diff --git a/src/Compiler/xlf/FSStrings.zh-Hant.xlf b/src/Compiler/xlf/FSStrings.zh-Hant.xlf
index 4e60f07d0a8..ba3f25a9471 100644
--- a/src/Compiler/xlf/FSStrings.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSStrings.zh-Hant.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support nullness.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         類型不符。必須是類型為\n    {1}    \n 的元組長度 {0},但提供的是類型為\n    {3}{4}\n 的元組長度 {2}
@@ -42,6 +62,16 @@
         插補字串 (部分)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         。請參閱 {0}。
diff --git a/src/FSharp.Build/FSharp.Build.fsproj b/src/FSharp.Build/FSharp.Build.fsproj
index ff97e84dad5..ea0465cc612 100644
--- a/src/FSharp.Build/FSharp.Build.fsproj
+++ b/src/FSharp.Build/FSharp.Build.fsproj
@@ -9,8 +9,9 @@
     FSharp.Build
     $(NoWarn);75 
     true
+    true
     $(DefineConstants);LOCALIZATION_FSBUILD
-    NU1701;FS0075
+    $(NoWarn);NU1701;FS0075
     true
     7.0  
     Debug;Release;Proto  
diff --git a/src/FSharp.Build/FSharpCommandLineBuilder.fs b/src/FSharp.Build/FSharpCommandLineBuilder.fs
index bf86d185edc..ae783fbcb80 100644
--- a/src/FSharp.Build/FSharpCommandLineBuilder.fs
+++ b/src/FSharp.Build/FSharpCommandLineBuilder.fs
@@ -15,7 +15,7 @@ do ()
 // Shim to match nullness checking library support in preview
 []
 module Utils =
-
+#if NO_CHECKNULLS
     /// Match on the nullness of an argument.
     let inline (|Null|NonNull|) (x: 'T) : Choice =
         match x with
@@ -24,7 +24,12 @@ module Utils =
 
     /// Indicates that a type may be null. 'MaybeNull' used internally in the F# compiler as unchecked
     /// replacement for 'string?' for example for future FS-1060.
-    type 'T MaybeNull when 'T: null and 'T: not struct = 'T
+    type MaybeNull<'T when 'T : null> = 'T
+#else
+    /// Indicates that a type may be null. 'MaybeNull' used internally in the F# compiler as unchecked
+    /// replacement for 'string?' for example for future FS-1060.
+    type MaybeNull<'T when 'T : __notnull and 'T : not struct> = 'T __withnull
+#endif
 
 type FSharpCommandLineBuilder() =
 
diff --git a/src/FSharp.Build/Fsc.fs b/src/FSharp.Build/Fsc.fs
index af7e16d13cc..5c44fdb8991 100644
--- a/src/FSharp.Build/Fsc.fs
+++ b/src/FSharp.Build/Fsc.fs
@@ -223,16 +223,13 @@ type public Fsc() as this =
         // checksumAlgorithm
         builder.AppendSwitchIfNotNull(
             "--checksumalgorithm:",
-            let ToUpperInvariant (s: string) =
-                if s = null then
-                    null
-                else
-                    s.ToUpperInvariant()
-
-            match ToUpperInvariant(checksumAlgorithm) with
-            | "SHA1" -> "Sha1"
-            | "SHA256" -> "Sha256"
-            | _ -> null
+            match checksumAlgorithm with
+            | Null -> null
+            | NonNull checksumAlgorithm ->
+                match checksumAlgorithm.ToUpperInvariant() with
+                | "SHA1" -> "Sha1"
+                | "SHA256" -> "Sha256"
+                | _ -> null
         )
 
         // Resources
diff --git a/src/FSharp.Build/SubstituteText.fs b/src/FSharp.Build/SubstituteText.fs
index 2e4950a62b3..97e8758ce55 100644
--- a/src/FSharp.Build/SubstituteText.fs
+++ b/src/FSharp.Build/SubstituteText.fs
@@ -24,7 +24,7 @@ type SubstituteText() =
     override _.Execute() =
         copiedFiles.Clear()
 
-        if not (isNull embeddedResources) then
+        if not (isNull (box embeddedResources)) then // this check can't fail, the type is non-nullable
             for item in embeddedResources do
                 // Update ITaskItem metadata to point to new location
                 let sourcePath = item.GetMetadata("FullPath")
diff --git a/src/FSharp.Core/FSharp.Core.fsproj b/src/FSharp.Core/FSharp.Core.fsproj
index 396618bb65d..54736d35ae9 100644
--- a/src/FSharp.Core/FSharp.Core.fsproj
+++ b/src/FSharp.Core/FSharp.Core.fsproj
@@ -28,7 +28,6 @@
     
     true
     true
-
     true
     FSharp.Core
     $(FSCorePackageVersion)
diff --git a/src/FSharp.Core/array.fs b/src/FSharp.Core/array.fs
index c3f9d35cdcb..d675f714ad9 100644
--- a/src/FSharp.Core/array.fs
+++ b/src/FSharp.Core/array.fs
@@ -831,12 +831,21 @@ module Array =
 
             count
 
+#if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
         let private createMask<'a>
             (f: 'a -> bool)
             (src: 'a array)
             (maskArrayOut: byref)
             (leftoverMaskOut: byref)
             =
+#else
+        let private createMask<'a>
+            (f: 'a -> bool)
+            (src: array<'a>)
+            (maskArrayOut: byref __withnull>)
+            (leftoverMaskOut: byref)
+            =
+#endif
             let maskArrayLength = src.Length / 0x20
 
             // null when there are less than 32 items in src array.
@@ -1026,7 +1035,11 @@ module Array =
 
             dstIdx
 
+#if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
         let private filterViaMask (maskArray: uint32 array) (leftoverMask: uint32) (count: int) (src: _ array) =
+#else
+        let private filterViaMask (maskArray: uint32 array __withnull) (leftoverMask: uint32) (count: int) (src: _ array) =
+#endif
             let dst = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked count
 
             let mutable dstIdx = 0
diff --git a/src/FSharp.Core/async.fs b/src/FSharp.Core/async.fs
index 2cfed9bc670..ce32e7ea3aa 100644
--- a/src/FSharp.Core/async.fs
+++ b/src/FSharp.Core/async.fs
@@ -868,7 +868,11 @@ module AsyncPrimitives =
 
     ///   - Initial cancellation check
     ///   - Call syncCtxt.Post with exception protection. THis may fail as it is arbitrary user code
+#if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
     let CreateSwitchToAsync (syncCtxt: SynchronizationContext) =
+#else
+    let CreateSwitchToAsync (syncCtxt: SynchronizationContext __withnull) =
+#endif
         MakeAsyncWithCancelCheck(fun ctxt -> ctxt.PostWithTrampoline syncCtxt ctxt.cont)
 
     ///   - Initial cancellation check
diff --git a/src/FSharp.Core/local.fs b/src/FSharp.Core/local.fs
index 6a3b44f5475..effc8e43426 100644
--- a/src/FSharp.Core/local.fs
+++ b/src/FSharp.Core/local.fs
@@ -1086,7 +1086,11 @@ module internal Array =
         if array.Length > 1 then 
             Array.Sort<_>(array, fastComparerForArraySort())
 
+#if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
     let stableSortWithKeysAndComparer (cFast:IComparer<'Key>) (c:IComparer<'Key>) (array:'T array) (keys: 'Key array)  =
+#else
+    let stableSortWithKeysAndComparer (cFast:IComparer<'Key> __withnull) (c:IComparer<'Key>) (array:array<'T>) (keys:array<'Key>)  =
+#endif
         // 'places' is an array or integers storing the permutation performed by the sort        
         let len = array.Length
         let places = zeroCreateUnchecked len
diff --git a/src/FSharp.Core/option.fs b/src/FSharp.Core/option.fs
index 46da0ec13a8..f872738b6e2 100644
--- a/src/FSharp.Core/option.fs
+++ b/src/FSharp.Core/option.fs
@@ -152,6 +152,7 @@ module Option =
         else
             None
 
+#if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
     []
     let inline ofObj value =
         match value with
@@ -163,6 +164,19 @@ module Option =
         match value with
         | None -> null
         | Some x -> x
+#else
+    []
+    let inline ofObj (value: 'T __withnull) : 'T option when 'T: not struct and 'T : __notnull = 
+        match value with
+        | null -> None
+        | _ -> Some value
+
+    []
+    let inline toObj (value: 'T option) : 'T __withnull when 'T: not struct (* and 'T : __notnull *)  =
+        match value with
+        | None -> null
+        | Some x -> x
+#endif
 
 module ValueOption =
 
@@ -315,6 +329,7 @@ module ValueOption =
         else
             ValueNone
 
+#if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
     []
     let ofObj value =
         match value with
@@ -326,3 +341,16 @@ module ValueOption =
         match value with
         | ValueNone -> null
         | ValueSome x -> x
+#else
+    []
+    let ofObj (value: 'T __withnull) : 'T voption when 'T: not struct and 'T : __notnull  = 
+        match value with
+        | null -> ValueNone
+        | _ -> ValueSome value
+
+    []
+    let toObj (value : 'T voption) : 'T __withnull when 'T: not struct (* and 'T : __notnull *) = 
+        match value with
+        | ValueNone -> null
+        | ValueSome x -> x
+#endif
diff --git a/src/FSharp.Core/option.fsi b/src/FSharp.Core/option.fsi
index ba65f231932..fe8b5ac044f 100644
--- a/src/FSharp.Core/option.fsi
+++ b/src/FSharp.Core/option.fsi
@@ -440,7 +440,12 @@ module Option =
     /// 
     /// 
     []
-    val inline ofObj: value: 'T -> 'T option when 'T: null
+#if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
+    val inline ofObj: value: 'T -> 'T option  when 'T : null
+#else
+    // TODO NULLNESS: assess this change - is it a breaking change?
+    val inline ofObj: value: 'T __withnull -> 'T option  when 'T : __notnull and 'T : not struct
+#endif
 
     /// Convert an option to a potentially null value.
     ///
@@ -455,7 +460,12 @@ module Option =
     /// 
     /// 
     []
-    val inline toObj: value: 'T option -> 'T when 'T: null
+#if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
+    val inline toObj: value: 'T option -> 'T when 'T : null
+#else
+    // TODO NULLNESS: assess this change - is it a breaking change?
+    val inline toObj: value: 'T option -> 'T __withnull when 'T : not struct (* and 'T : __notnull *)
+#endif
 
 /// Contains operations for working with value options.
 ///
@@ -888,7 +898,12 @@ module ValueOption =
     /// 
     /// 
     []
-    val ofObj: value: 'T -> 'T voption when 'T: null
+#if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
+    val ofObj: value: 'T -> 'T voption  when 'T : null
+#else
+    // TODO NULLNESS: assess this change - is it a breaking change?
+    val ofObj: value: 'T __withnull -> 'T voption  when 'T : not struct and 'T : __notnull
+#endif
 
     /// Convert an option to a potentially null value.
     ///
@@ -903,4 +918,9 @@ module ValueOption =
     /// 
     /// 
     []
-    val toObj: value: 'T voption -> 'T when 'T: null
+#if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
+    val toObj: value: 'T voption -> 'T when 'T : null
+#else
+    // TODO NULLNESS: assess this change - is it a breaking change?
+    val toObj: value: 'T voption -> 'T __withnull when 'T : not struct (* and 'T : __notnull *)
+#endif
diff --git a/src/FSharp.Core/prim-types.fs b/src/FSharp.Core/prim-types.fs
index e05a55fa47b..5475ac66ea3 100644
--- a/src/FSharp.Core/prim-types.fs
+++ b/src/FSharp.Core/prim-types.fs
@@ -9,6 +9,8 @@
 #nowarn "69" // Interface implementations should normally be given on the initial declaration of a type. Interface implementations in augmentations may lead to accessing static bindings before they are initialized, though only if the interface implementation is invoked during initialization of the static data, and in turn access the static data. You may remove this warning using #nowarn "69" if you have checked this is not the case.
 #nowarn "77" // Member constraints with the name 'Exp' are given special status by the F# compiler...
 #nowarn "3218" // mismatch of parameter name for 'fst' and 'snd'
+#nowarn "3244" // no nullness checking
+#nowarn "3245" // no nullness checking
 
 namespace Microsoft.FSharp.Core
 
@@ -4222,8 +4224,8 @@ namespace Microsoft.FSharp.Core
             | _ -> None
 
         []
-        let inline isNull (value : 'T) = 
-            match value with 
+        let inline isNull (value : 'T when 'T : null) = 
+            match box value with 
             | null -> true 
             | _ -> false
 
@@ -4233,6 +4235,62 @@ namespace Microsoft.FSharp.Core
             | null -> false 
             | _ -> true
 
+#if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT
+
+        []
+        let inline isNullV (value : Nullable<'T>) = not value.HasValue
+
+        []
+        let inline nonNull (value : 'T __withnull when 'T : __notnull and 'T : not struct) = 
+            match box value with 
+            | null -> raise (NullReferenceException()) 
+            | _ -> (# "" value : 'T #)
+
+        []
+        let inline nonNullV (value : Nullable<'T>) = 
+            if value.HasValue then 
+                value.Value
+            else 
+                raise (NullReferenceException())
+
+        []
+        let inline (|Null|NonNull|) (value : 'T __withnull when 'T : __notnull and 'T : not struct) = 
+            match value with 
+            | null -> Null () 
+            | _ -> NonNull (# "" value : 'T #)
+
+        []
+        let inline (|NullV|NonNullV|) (value : Nullable<'T>) = 
+            if value.HasValue then NonNullV value.Value
+            else NullV ()
+
+        []
+        let inline (|NonNullQuick|) (value : 'T __withnull when 'T : __notnull and 'T : not struct) =
+            match box value with 
+            | null -> raise (NullReferenceException()) 
+            | _ -> (# "" value : 'T #)
+
+        []
+        let inline (|NonNullQuickV|) (value : Nullable<'T>) =
+            if value.HasValue then value.Value
+            else raise (NullReferenceException()) 
+
+        []
+        let inline withNull (value : 'T when 'T : __notnull and 'T : not struct) = (# "" value : 'T __withnull #)
+
+        []
+        let inline withNullV (value : 'T) : Nullable<'T> = Nullable<'T>(value)
+
+        []
+        let inline nullV<'T when 'T : struct and 'T : (new : unit -> 'T) and 'T :> ValueType>  = Nullable<'T>()
+
+        []
+        let inline nullArgCheck (argumentName:string) (value: 'T __withnull when 'T : __notnull and 'T : not struct) = 
+            match value with 
+            | null -> raise (new ArgumentNullException(argumentName))        
+            | _ ->  (# "" value : 'T #)
+#endif
+
         []
         let inline raise (exn: exn) =
             (# "throw" exn : 'T #)
@@ -4325,6 +4383,16 @@ namespace Microsoft.FSharp.Core
         []
         let defaultValueArg arg defaultValue = match arg with ValueNone -> defaultValue | ValueSome v -> v
 
+#if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT
+        []
+        let inline defaultIfNull defaultValue (arg: 'T __withnull when 'T : __notnull and 'T : not struct) = 
+            match arg with null -> defaultValue | _ -> (# "" arg : 'T #)
+        
+        []
+        let inline defaultIfNullV defaultValue (arg: Nullable<'T>) = 
+            if arg.HasValue then arg.Value else defaultValue
+#endif
+
         []
         let inline (~-) (n: ^T) : ^T = 
              UnaryNegationDynamic<(^T), (^T)> n
diff --git a/src/FSharp.Core/prim-types.fsi b/src/FSharp.Core/prim-types.fsi
index bcbfa77e320..b547b26a7d2 100644
--- a/src/FSharp.Core/prim-types.fsi
+++ b/src/FSharp.Core/prim-types.fsi
@@ -1343,7 +1343,11 @@ namespace Microsoft.FSharp.Core
         val inline FastGenericComparer<'T> : System.Collections.Generic.IComparer<'T> when 'T: comparison 
 
         /// Make an F# comparer object for the given type, where it can be null if System.Collections.Generic.Comparer<'T>.Default
-        val internal FastGenericComparerCanBeNull<'T> : System.Collections.Generic.IComparer<'T> when 'T: comparison 
+#if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
+        val internal FastGenericComparerCanBeNull<'T>  : System.Collections.Generic.IComparer<'T> when 'T : comparison 
+#else
+        val internal FastGenericComparerCanBeNull<'T>  : System.Collections.Generic.IComparer<'T> __withnull when 'T : comparison 
+#endif
 
         /// Make an F# hash/equality object for the given type
         val inline FastGenericEqualityComparer<'T> : System.Collections.Generic.IEqualityComparer<'T> when 'T: equality
@@ -3098,6 +3102,24 @@ namespace Microsoft.FSharp.Core
         /// 
         val inline (<|||): func: ('T1 -> 'T2 -> 'T3 -> 'U) -> arg1: 'T1 * arg2: 'T2 * arg3: 'T3 -> 'U
 
+#if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT
+        /// Used to specify a default value for a nullable reference argument in the implementation of a function
+        /// The default value of the argument.
+        /// A nullable value representing the argument.
+        /// The argument value. If it is null, the defaultValue is returned.
+        []
+        []
+        val inline defaultIfNull : defaultValue:'T -> arg:'T __withnull -> 'T when 'T : __notnull and 'T : not struct 
+
+        /// Used to specify a default value for an nullable value argument in the implementation of a function
+        /// The default value of the argument.
+        /// A nullable value representing the argument.
+        /// The argument value. If it is null, the defaultValue is returned.
+        []
+        []
+        val inline defaultIfNullV : defaultValue:'T -> arg:Nullable<'T> -> 'T 
+#endif
+
         /// Used to specify a default value for an optional argument in the implementation of a function
         ///
         /// An option representing the argument.
@@ -3395,13 +3417,92 @@ namespace Microsoft.FSharp.Core
         []
         val inline isNull: value: 'T -> bool when 'T: null
         
+#if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT
+        /// Determines whether the given value is null.
+        /// The value to check.
+        /// A choice indicating whether the value is null or not-null.
+        []
+        []
+        val inline (|Null|NonNull|) : value: 'T __withnull -> Choice  when 'T : __notnull and 'T : not struct
+        
+        /// Determines whether the given value is null.
+        /// In a future revision of nullness support this may be unified with 'Null|NonNull'.
+        /// The value to check.
+        /// A choice indicating whether the value is null or not-null.
+        []
+        []
+        val inline (|NullV|NonNullV|) : value: Nullable<'T> -> Choice 
+        
+        /// When used in a pattern checks the given value is not null.
+        /// The value to check.
+        /// The non-null value.
+        []
+        []
+        val inline (|NonNullQuick|) : value: 'T __withnull -> 'T when 'T : __notnull and 'T : not struct
+        
+        /// When used in a pattern checks the given value is not null.
+        /// In a future revision of nullness support this may be unified with 'NonNullQuick'.
+        /// The value to check.
+        /// The non-null value.
+        []
+        []
+        val inline (|NonNullQuickV|) : value: Nullable<'T> -> 'T 
+        
+        /// Determines whether the given value is null.
+        /// In a future revision of nullness support this may be unified with 'isNull'.
+        /// The value to check.
+        /// True when value is null, false otherwise.
+        []
+        []
+        val inline isNullV : value:Nullable<'T> -> bool
+#endif
+
         /// Determines whether the given value is not null.
         ///
         /// The value to check.
         ///
         /// True when value is not null, false otherwise.
         []
-        val inline internal isNotNull: value: 'T -> bool when 'T: null
+        val inline internal isNotNull: value:'T -> bool when 'T : null
+
+#if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT
+        /// Get the null value for a value type.
+        /// In a future revision of nullness support this may be unified with 'null'.
+        /// The null value for a value type.
+        []
+        []
+        val inline nullV<'T when 'T : struct and 'T : (new : unit -> 'T) and 'T :> ValueType> :  Nullable<'T>
+
+        /// Asserts that the value is non-null.
+        /// The value to check.
+        /// The value when it is not null. If the value is null an exception is raised.
+        []
+        []
+        val inline nonNull : value: 'T __withnull -> 'T when 'T : __notnull and 'T : not struct
+
+        /// Asserts that the value is non-null.
+        /// In a future revision of nullness support this may be unified with 'nonNull'.
+        /// The value to check.
+        /// True when value is null, false otherwise.
+        []
+        []
+        val inline nonNullV : value:Nullable<'T> -> 'T 
+
+        /// Asserts that the value is non-null.
+        /// The value to check.
+        /// True when value is null, false otherwise.
+        []
+        []
+        val inline withNull : value:'T -> 'T __withnull when 'T : __notnull and 'T : not struct
+
+        /// Asserts that the value is non-null.
+        /// In a future revision of nullness support this may be unified with 'withNull'.
+        /// The value to check.
+        /// True when value is null, false otherwise.
+        []
+        []
+        val inline withNullV : value:'T -> Nullable<'T> 
+#endif
 
         /// Throw a  exception.
         ///
@@ -3467,6 +3568,17 @@ namespace Microsoft.FSharp.Core
         []
         val inline nullArg: argumentName: string -> 'T 
 
+#if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT
+        /// Throw a System.ArgumentNullException if the given value is null exception
+        /// 
+        /// The argument name.
+        /// 
+        /// The result value.
+        []
+        []
+        val inline nullArgCheck : argumentName:string -> 'T __withnull -> 'T when 'T : __notnull and 'T : not struct
+#endif
+
         /// Throw a  exception
         ///
         /// The exception message.
@@ -3641,7 +3753,7 @@ namespace Microsoft.FSharp.Core
         /// otherwise raise an exception. Calls .
         ///
         /// The exit code to use.
-        /// 
+        ///
         /// Never returns.
         /// 
         /// 
diff --git a/src/fsi/console.fs b/src/fsi/console.fs
index 4e68d2aea0b..a56b3f4e4f7 100644
--- a/src/fsi/console.fs
+++ b/src/fsi/console.fs
@@ -7,6 +7,18 @@ open System.Text
 open System.Collections.Generic
 open FSharp.Compiler.DiagnosticsLogger
 
+[]
+module internal ConsoleHelpers =
+
+#if NO_CHECKNULLS
+  type MaybeNull<'T when 'T : null> = 'T
+
+  // Shim to match nullness checking library support in preview
+  let inline (|Null|NonNull|) (x: 'T) : Choice = match x with null -> Null | v -> NonNull v
+#else
+  type MaybeNull<'T when 'T : __notnull> = 'T __withnull
+#endif
+
 type internal Style =
     | Prompt
     | Out
@@ -29,24 +41,20 @@ type internal History() =
         list.Clear()
         current <- -1
 
-    member _.Add line =
-        match line with
-        | null
+    member _.Add (line: string MaybeNull) = 
+        match line with 
+        | Null
         | "" -> ()
-        | _ -> list.Add(line)
+        | NonNull line -> list.Add(line)
 
-    member _.AddLast line =
-        match line with
-        | null
+    member _.AddLast (line: string MaybeNull) =  
+        match line with 
+        | Null
         | "" -> ()
-        | _ ->
+        | NonNull line ->
             list.Add(line)
             current <- list.Count
 
-    // Dead code
-    // member x.First() = current <- 0; x.Current
-    // member x.Last() = current <- list.Count - 1; x.Current
-
     member x.Previous() =
         if (list.Count > 0) then
             current <- ((current - 1) + list.Count) % list.Count
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/BindingExpressions/in05.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/BindingExpressions/in05.fs
index 583f27de4e8..0c386d1676d 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/BindingExpressions/in05.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/BindingExpressions/in05.fs
@@ -4,9 +4,9 @@
 // I'm adding these cases to make sure we do not accidentally change the behavior from version to version
 // Eventually, we will deprecated them - and the specs will be updated.
 //The type 'int' does not match the type 'unit'$
-//Type mismatch\. Expecting a.    ''a -> 'b'    .but given a.    ''a -> unit'    .The type 'int' does not match the type 'unit'$
 //The result of this expression has type 'bool' and is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$
-module E
+
+module E = 
     let a = 3 in
         a + 1 |> ignore
         a + 1 |> ignore
diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
index 3dacfbfde6e..e62cdf6822c 100644
--- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeEqualsMissingTests.fs
@@ -6,16 +6,16 @@ open Xunit
 open FSharp.Test
 open FSharp.Compiler.Diagnostics
 
+// Disabled this test, see https://github.com/dotnet/fsharp/commit/98dc1b09fa1ff15176998dc2d28c5b5c8d0f80b1#r43542750
+//module ``Type definition missing equals`` =
 
-module ``Type definition missing equals`` =
-
-    []
-    let ``Missing equals in DU``() =
-        CompilerAssert.TypeCheckSingleError
-            """
-type X | A | B
-            """
-            FSharpDiagnosticSeverity.Error
-            3360 
-            (2, 8, 2, 9)
-            "Unexpected token in type definition. Expected '=' after the type 'X'."
+//     []
+//     let ``Missing equals in DU``() =
+//         CompilerAssert.TypeCheckSingleError
+//             """
+// type X | A | B
+//             """
+//             FSharpDiagnosticSeverity.Error
+//             3360 
+//             (2, 8, 2, 9)
+//             "Unexpected token in type definition. Expected '=' after the type 'X'."
diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl
index 0faf9512f36..b067bd9ef51 100644
--- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl
+++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl
@@ -11341,4 +11341,35 @@ FSharp.Compiler.Xml.XmlDoc: System.String GetXmlText()
 FSharp.Compiler.Xml.XmlDoc: System.String[] GetElaboratedXmlLines()
 FSharp.Compiler.Xml.XmlDoc: System.String[] UnprocessedLines
 FSharp.Compiler.Xml.XmlDoc: System.String[] get_UnprocessedLines()
-FSharp.Compiler.Xml.XmlDoc: Void .ctor(System.String[], FSharp.Compiler.Text.Range)
\ No newline at end of file
+FSharp.Compiler.Xml.XmlDoc: Void .ctor(System.String[], FSharp.Compiler.Text.Range)
+FSharp.Compiler.Symbols.FSharpType: Boolean HasNullAnnotation
+FSharp.Compiler.Symbols.FSharpType: Boolean IsNullAmbivalent
+FSharp.Compiler.Symbols.FSharpType: Boolean get_HasNullAnnotation()
+FSharp.Compiler.Symbols.FSharpType: Boolean get_IsNullAmbivalent()
+FSharp.Compiler.Syntax.SynType+StaticConstantNull: FSharp.Compiler.Text.Range get_range()
+FSharp.Compiler.Syntax.SynType+StaticConstantNull: FSharp.Compiler.Text.Range range
+FSharp.Compiler.Syntax.SynType+Tags: Int32 StaticConstantNull
+FSharp.Compiler.Syntax.SynType+Tags: Int32 WithNull
+FSharp.Compiler.Syntax.SynType+WithNull: Boolean ambivalent
+FSharp.Compiler.Syntax.SynType+WithNull: Boolean get_ambivalent()
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Syntax.SynType get_innerType()
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Syntax.SynType innerType
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Text.Range get_range()
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Text.Range range
+FSharp.Compiler.Syntax.SynType: Boolean IsStaticConstantNull
+FSharp.Compiler.Syntax.SynType: Boolean IsWithNull
+FSharp.Compiler.Syntax.SynType: Boolean get_IsStaticConstantNull()
+FSharp.Compiler.Syntax.SynType: Boolean get_IsWithNull()
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewStaticConstantNull(FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewWithNull(FSharp.Compiler.Syntax.SynType, Boolean, FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+StaticConstantNull
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+WithNull
+FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparNotSupportsNull
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Syntax.SynTypar genericName
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Syntax.SynTypar get_genericName()
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Text.Range get_range()
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Text.Range range
+FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparNotSupportsNull
+FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparNotSupportsNull()
+FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparNotSupportsNull(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull
diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/BigIntType.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/BigIntType.fs
index caa7e84591c..8e0a6eb44f1 100644
--- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/BigIntType.fs
+++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/BigIntType.fs
@@ -93,7 +93,7 @@ type BigIntType() =
         Assert.True(z4.Equals(z4))
 
         // Null
-        Assert.False(a.Equals(null))
+        Assert.False(a.Equals(null:obj)) // TODO NULLNESS - this type annoation was needed to resolve overloading, even with --checknulls off
 
         Assert.True(0I.GetHashCode() = (BigInteger()).GetHashCode())
     
diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/OptionModule.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/OptionModule.fs
index cecad68f233..7b0ff69b420 100644
--- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/OptionModule.fs
+++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/OptionModule.fs
@@ -131,7 +131,7 @@ type OptionModule() =
     member this.OfToObj() =
         Assert.True( Option.toObj (Some "3") = "3")
         Assert.True( Option.toObj (Some "") = "")
-        Assert.True( Option.toObj (Some null) = null)
+        Assert.True( Option.toObj (Some null) = null) // TODO NULLNESS: this type annotation should not be needed 
         Assert.True( Option.toObj None = null)     
      
         Assert.True( Option.ofObj "3" = Some "3")
@@ -369,7 +369,7 @@ type ValueOptionTests() =
     member this.OfToObj() =
         Assert.True(ValueOption.toObj (ValueSome "3") = "3")
         Assert.True(ValueOption.toObj (ValueSome "") = "")
-        Assert.True(ValueOption.toObj (ValueSome null) = null)
+        Assert.True(ValueOption.toObj (ValueSome null) = null)  // TODO NULLNESS: this type annotation should not be needed
         Assert.True(ValueOption.toObj ValueNone = null)     
      
         Assert.True(ValueOption.ofObj "3" = ValueSome "3")
diff --git a/tests/fsharp/Compiler/Regressions/NullableOptionalRegressionTests.fs b/tests/fsharp/Compiler/Regressions/NullableOptionalRegressionTests.fs
index c4009ee5233..341955aa7c8 100644
--- a/tests/fsharp/Compiler/Regressions/NullableOptionalRegressionTests.fs
+++ b/tests/fsharp/Compiler/Regressions/NullableOptionalRegressionTests.fs
@@ -8,7 +8,8 @@ open FSharp.Test.Compiler
 []
 module NullableOptionalRegressionTests =
 
-    []
+    //Disabled, see RFC for nullable
+    //[]
     let ``Should compile with generic overloaded nullable methods``() =
         Fsx """
 open System
diff --git a/tests/fsharp/tests.fs b/tests/fsharp/tests.fs
index e29ae44733b..bfdb893c2dc 100644
--- a/tests/fsharp/tests.fs
+++ b/tests/fsharp/tests.fs
@@ -36,8 +36,69 @@ let testConfig = getTestsDirectory >> testConfig
 []
 module CoreTests =
 
+
 #if !NETCOREAPP
-// This test stays in FsharpSuite for a later migration phases, it uses hardcoded #r to a C# compiled cslib.dll inside
+    []
+    let ``subtype-langversion-preview-checknulls`` () =
+        let cfg = testConfig "core/subtype"
+
+        use testOkFile = fileguard cfg "test.ok"
+
+        fsc cfg "%s -o:test-checknulls.exe -g --langversion:preview --checknulls" cfg.fsc_flags ["test.fsx"]
+
+        exec cfg ("." ++ "test-checknulls.exe") ""
+
+        testOkFile.CheckExists()
+
+    []
+    let ``subtype-langversion-preview-no-checknulls`` () =
+        let cfg = testConfig "core/subtype"
+
+        use testOkFile = fileguard cfg "test.ok"
+
+        fsc cfg "%s -o:test-no-checknulls.exe -g --langversion:preview --checknulls-" cfg.fsc_flags ["test.fsx"]
+
+        exec cfg ("." ++ "test-no-checknulls.exe") ""
+
+        testOkFile.CheckExists()
+
+    []
+    let ``subtype-langversion-46`` () =
+        let cfg = testConfig "core/subtype"
+
+        use testOkFile = fileguard cfg "test.ok"
+
+        fsc cfg "%s -o:test-langversion-46.exe -g --langversion:4.6" cfg.fsc_flags ["test.fsx"]
+
+        exec cfg ("." ++ "test-langversion-46.exe") ""
+
+        testOkFile.CheckExists()
+
+    []
+    let nullness_no_checknulls () =
+        let cfg = testConfig "core/nullness"
+
+        use testOkFile = fileguard cfg "test.ok"
+
+        fsc cfg "%s -o:test-no-checknulls.exe -g --langversion:preview --define:NO_CHECKNULLS" cfg.fsc_flags ["test.fsx"]
+
+        exec cfg ("." ++ "test-no-checknulls.exe") ""
+
+        testOkFile.CheckExists()
+
+    []
+    let nullness_checknulls () =
+        let cfg = testConfig "core/nullness"
+
+        use testOkFile = fileguard cfg "test.ok"
+
+        fsc cfg "%s -o:test-checknulls.exe -g --checknulls --langversion:preview" cfg.fsc_flags ["test.fsx"]
+
+        exec cfg ("." ++ "test-checknulls.exe") ""
+
+        testOkFile.CheckExists()
+
+    // This test stays in FsharpSuite for a later migration phases, it uses hardcoded #r to a C# compiled cslib.dll inside
     []
     let ``quotes-FSC-FSC_DEBUG`` () = singleTestBuildAndRun "core/quotes" FSC_DEBUG
 
@@ -1025,6 +1086,31 @@ module CoreTests =
     []
     let ``libtest-FSC_NETFX_TEST_ROUNDTRIP_AS_DLL`` () = singleTestBuildAndRun "core/libtest" FSC_NETFX_TEST_ROUNDTRIP_AS_DLL
 
+    []
+    let ``libtest-langversion-preview-checknulls`` () =
+        let cfg = testConfig "core/libtest"
+
+        use testOkFile = fileguard cfg "test.ok"
+
+        fsc cfg "%s -o:test-checknulls.exe -g --langversion:preview --checknulls" cfg.fsc_flags ["test.fsx"]
+
+        exec cfg ("." ++ "test-checknulls.exe") ""
+
+        testOkFile.CheckExists()
+
+ 
+    []
+    let ``libtest-langversion-46`` () =
+        let cfg = testConfig "core/libtest"
+
+        use testOkFile = fileguard cfg "test.ok"
+
+        fsc cfg "%s -o:test-langversion-46.exe -g --langversion:4.6" cfg.fsc_flags ["test.fsx"]
+
+        exec cfg ("." ++ "test-langversion-46.exe") ""
+
+        testOkFile.CheckExists()
+
     []
     let ``no-warn-2003-tests`` () =
         // see https://github.com/dotnet/fsharp/issues/3139
diff --git a/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.fsx b/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.fsx
index 947735d0e84..72bfdad9c21 100644
--- a/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.fsx
+++ b/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.fsx
@@ -13,7 +13,7 @@ type Plus =
     inherit Default1
     static member inline ``+`` (x: 'Plus             , y: 'Plus             ,             _mthd: Default2) = (^Plus :  (static member (<|>) : _*_ -> _) x, y) : ^Plus
     static member inline ``+`` (x: 'Plus             , y: 'Plus             , []_mthd: Default1) = x + y : ^Plus
-    static member inline ``+`` (_: ^t when ^t: null and ^t: struct, _: ^t   , []_mthd: Default1) = id
+
     
     static member inline Invoke (x: 'Plus) (y: 'Plus) : 'Plus =
         let inline call (mthd : ^M, input1 : ^I, input2 : ^I) = ((^M or ^I) : (static member ``+`` : _*_*_ -> _) input1, input2, mthd)
@@ -49,9 +49,9 @@ type Zero =
   inherit Default1
   static member inline Zero (_: 't                             , _: Default3) = (^t : (static member Empty : ^t) ()) : 't
   static member inline Zero (_: 't                             , _: Default2) = FromInt32.Invoke 0             : 't
-  static member inline Zero (_: ^t when ^t: null and ^t: struct, _: Default2) = id
+
   static member inline Zero (_: 't                             , _: Default1) = LanguagePrimitives.GenericZero : 't
-  static member inline Zero (_: ^t when ^t: null and ^t: struct, _: Default1) = id
+
   static member        Zero (_: System.TimeSpan                , _: Zero    ) = System.TimeSpan ()
   static member        Zero (_: list<'a>                       , _: Zero    ) = []   :   list<'a>
   static member        Zero (_: option<'a>                     , _: Zero    ) = None : option<'a>
diff --git a/tests/fsharp/typecheck/sigs/neg04.bsl b/tests/fsharp/typecheck/sigs/neg04.bsl
index 25a4a425582..57638b360fc 100644
--- a/tests/fsharp/typecheck/sigs/neg04.bsl
+++ b/tests/fsharp/typecheck/sigs/neg04.bsl
@@ -30,7 +30,7 @@ neg04.fs(47,30,47,51): typecheck error FS0001: Type mismatch. Expecting a
     'seq<'a> -> 'n'    
 but given a
     ''o list -> 'p'    
-The type 'seq<'a>' does not match the type ''n list'
+The type ''n list' does not match the type 'seq<'a>'
 
 neg04.fs(47,49,47,51): typecheck error FS0784: This numeric literal requires that a module 'NumericLiteralN' defining functions FromZero, FromOne, FromInt32, FromInt64 and FromString be in scope
 
@@ -38,7 +38,7 @@ neg04.fs(47,30,47,51): typecheck error FS0001: Type mismatch. Expecting a
     'seq<'a> -> 'n'    
 but given a
     ''o list -> 'p'    
-The type 'seq<'a>' does not match the type ''n list'
+The type ''n list' does not match the type 'seq<'a>'
 
 neg04.fs(61,25,61,40): typecheck error FS0001: This expression was expected to have type
     'ClassType1'    
diff --git a/tests/fsharp/typecheck/sigs/neg20.bsl b/tests/fsharp/typecheck/sigs/neg20.bsl
index 88f483967e4..095ec90fd47 100644
--- a/tests/fsharp/typecheck/sigs/neg20.bsl
+++ b/tests/fsharp/typecheck/sigs/neg20.bsl
@@ -90,19 +90,19 @@ neg20.fs(108,12,108,16): typecheck error FS0001: Type mismatch. Expecting a
     'B * B -> 'a'    
 but given a
     'A * A -> Data'    
-The type 'B' does not match the type 'A'
+The type 'A' does not match the type 'B'
 
 neg20.fs(109,12,109,16): typecheck error FS0001: Type mismatch. Expecting a
     'A * B -> 'a'    
 but given a
     'A * A -> Data'    
-The type 'B' does not match the type 'A'
+The type 'A' does not match the type 'B'
 
 neg20.fs(110,12,110,16): typecheck error FS0001: Type mismatch. Expecting a
     'B * A -> 'a'    
 but given a
     'A * A -> Data'    
-The type 'B' does not match the type 'A'
+The type 'A' does not match the type 'B'
 
 neg20.fs(128,19,128,22): typecheck error FS0001: This expression was expected to have type
     'string'    
diff --git a/vsintegration/src/FSharp.VS.FSI/fsiBasis.fs b/vsintegration/src/FSharp.VS.FSI/fsiBasis.fs
index 8e4d3974761..771b9c0c979 100644
--- a/vsintegration/src/FSharp.VS.FSI/fsiBasis.fs
+++ b/vsintegration/src/FSharp.VS.FSI/fsiBasis.fs
@@ -38,11 +38,12 @@ module internal Guids =
     let guidFSharpProjectPkgString      = "91A04A73-4F2C-4E7C-AD38-C1A68E7DA05C" // FSI-LINKAGE-POINT: when packaged in project system
 
     []
-    /// "35A5E6B8-4012-41fc-A652-2CDC56D74E9F"
+
+    // "35A5E6B8-4012-41fc-A652-2CDC56D74E9F"
     let guidFsiLanguageService          = "35A5E6B8-4012-41fc-A652-2CDC56D74E9F"        // The FSI lang service
 
     []
-    /// "dee22b65-9761-4a26-8fb2-759b971d6dfc"
+    // "dee22b65-9761-4a26-8fb2-759b971d6dfc"
     let guidFsiSessionToolWindow        = "dee22b65-9761-4a26-8fb2-759b971d6dfc"
 
     // FSI Package command set

From 5fc50c93c027284a5ea170e09ee9b622997c40a2 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Wed, 24 May 2023 15:22:40 +0100
Subject: [PATCH 02/59] squash

---
 tests/fsharp/core/nullness/nullness.fsproj |  23 ++
 tests/fsharp/core/nullness/test.fsx        | 450 +++++++++++++++++++++
 2 files changed, 473 insertions(+)
 create mode 100644 tests/fsharp/core/nullness/nullness.fsproj
 create mode 100644 tests/fsharp/core/nullness/test.fsx

diff --git a/tests/fsharp/core/nullness/nullness.fsproj b/tests/fsharp/core/nullness/nullness.fsproj
new file mode 100644
index 00000000000..c8e48a4c144
--- /dev/null
+++ b/tests/fsharp/core/nullness/nullness.fsproj
@@ -0,0 +1,23 @@
+
+
+  
+    net7.0
+    ..\..\..\..\artifacts\bin\fsc\$(Configuration)\net472
+    fsc.exe
+    
+    Exe
+    true
+    
+	$(OtherFlags) --nowarn:1204
+    
+	$(OtherFlags) --nowarn:57
+	$(OtherFlags) --langversion:preview
+
+  
+
+  
+	
+  
+  
+
+
diff --git a/tests/fsharp/core/nullness/test.fsx b/tests/fsharp/core/nullness/test.fsx
new file mode 100644
index 00000000000..bebdb7a1c0e
--- /dev/null
+++ b/tests/fsharp/core/nullness/test.fsx
@@ -0,0 +1,450 @@
+let failures = ref []
+
+let report_failure (s : string) = 
+    stderr.Write" NO: "
+    stderr.WriteLine s
+    failures := !failures @ [s]
+
+let test (s : string) b = 
+    stderr.Write(s)
+    if b then stderr.WriteLine " OK"
+    else report_failure (s)
+
+let check s v1 v2 = test s (v1 = v2)
+
+open System
+open System.Diagnostics
+open System.Runtime.CompilerServices
+
+
+module Extractions0a =
+
+    let x = null
+    let result = (x = "") // expect no warning
+
+module Extractions0b =
+
+    let x = null
+    let f (x: 'T, y: 'T) = ()
+    let result = f (x, "")   // expect no warning
+
+#if NEGATIVE
+// This give a warning since 'T is not known to be reference type non-null
+let f<'T> (x: 'T __withnull, y: 'T __withnull) = ()
+#endif
+
+module Extractions0c =
+
+    let x = null
+    let f<'T when 'T : __notnull> (x: 'T __withnull, y: 'T __withnull) = ()
+    let s : string = ""
+    let result = f (x, s)   // expect no warning
+
+module Extractions0d =
+
+    let x = null
+    let f<'T when 'T : null> (x: 'T, y: 'T) = ()
+    let result = f (x, "")  // expect no warning
+
+module Extractions0e =
+
+    let x = null
+    let f<'T when 'T : __notnull> (x: 'T __withnull, y: 'T __withnull) = ()
+    let result = f (x, "") // expect no warning
+
+module Extractions1 =
+
+    let mutable x : _ __withnull = null
+    x <- ""  // expect no warning
+
+module Extractions2 =
+    open System.Diagnostics
+
+    let f (x: ActivitySource) =
+       x.CreateActivity("aaa", ActivityKind.Client)
+
+    let source = new ActivitySource("aaab")
+    let activity = f source
+    let baggage = activity.Baggage // TODO NULLNESS: should trigger a nullness warning
+
+    // TODO NULLNESS test matrix
+    // - Import null annotated .NET non-generic type (above)
+    // - Import null annotated .NET array type
+    // - Import null annotated .NET generic type instantiated at non-null .NET type 
+    // - Import .NET generic type instantiated at null annotated .NET type 
+
+
+//let f<'T when 'T : not struct> (x: 'T __withnull) = 1
+
+(*
+module Basics =     
+    let x1 : string = null // ** Expected to give a Nullness warning
+    check "ekjnceoiwe1" x1 null // ** Expected to give a Nullness warning
+    let x2 : string __withnull = null
+    check "ekjnceoiwe2" x2 null
+    let x3 : string __withnull = "a"
+    check "ekjnceoiwe3" x3 "a"
+    let x4 : string = ""
+    check "ekjnceoiwe4" x4 ""
+
+    let x5 = nonNull "" // Should not give a Nullness warning
+    check "ekjnceoiwe5" x5 ""
+    let x6 = nonNull "" // **Expected to give a Nullness warning, expected also to give a warning with nullness checking off
+    check "ekjnceoiwe6" x6 ""
+    let x7 = nonNull ""
+    check "ekjnceoiwe7" x7 ""
+    let _x7 : string = x7
+    let x8 = nonNull Array.empty
+    check "ekjnceoiwe8" x8 [| |]
+    let x9 = nonNull [| "" |]
+    check "ekjnceoiwe9" x9 [| "" |]
+    let x10 = nonNullV (Nullable(3))
+    check "ekjnceoiwe10" x10 3
+    let x11 = try nonNullV (Nullable()) with :? System.NullReferenceException -> 10
+    check "ekjnceoiwe11" x11 10
+    let x12 = nullV
+    check "ekjnceoiwe12" x12 (Nullable())
+    let x13 = nullV
+    check "ekjnceoiwe13" x13 (Nullable())
+    let x14 = withNullV 6L
+    check "ekjnceoiwe14" x14 (Nullable(6L))
+    let x15 : string __withnull = withNull x4
+    check "ekjnceoiwe15" x15 ""
+    let x15a : string __withnull = withNull ""
+    check "ekjnceoiwe15a" x15a ""
+    let x15b : string __withnull = withNull x4
+    check "ekjnceoiwe15b" x15b ""
+    let x15c : string __withnull = withNull x4 // **Expected to give a Nullness warning
+    check "ekjnceoiwe15c" x15c ""
+    let x16 : Nullable = withNullV 3
+    check "ekjnceoiwe16" x16 (Nullable(3))
+    
+    let y0 = isNull null // Should not give a Nullness warning (obj)
+    check "ekjnceoiwey0" y0 true
+    let y1 = isNull (null: obj __withnull) // Should not give a Nullness warning
+    check "ekjnceoiwey1" y1 true
+    let y1b = isNull (null: string __withnull) // Should not give a Nullness warning
+    check "ekjnceoiwey1b" y1b true
+    let y2 = isNull "" // **Expected to give a Nullness warning - type instantiation of a nullable type is non-nullable string
+    check "ekjnceoiwey2" y2 false
+    let y9 = isNull "" // **Expected to give a Nullness warning - type instantiation of a nullable type is non-nullable string
+    check "ekjnceoiwey9" y9 false
+    let y10 = isNull "" // Should not give a Nullness warning.
+    check "ekjnceoiwey10" y10 false
+
+module NotNullConstraint =
+    let f3 (x: 'T when 'T : __notnull) = 1
+    let v1 = f3 1 
+    check "ekjnceoiwev1" v1 1
+    let v2 = f3 "a"
+    check "ekjnceoiwev2" v2 1
+    let v3 = f3 (null: obj __withnull) // Expect to give a warning
+    check "ekjnceoiwev3" v3 1
+    let v4 = f3 (null: string __withnull) // Expect to give a warning
+    check "ekjnceoiwev4" v4 1
+#if NEGATIVE
+    f3 (Some 1) // Expect to give an error
+#endif
+
+    let w1 = 1 |> f3
+    check "ekjnceoiwew1" w1 1
+    let w2 = "a" |> f3
+    check "ekjnceoiwew2" w2 1
+    let w3 = (null: obj __withnull) |> f3 // Expect to give a warning
+    check "ekjnceoiwew3" w3 1
+    let w4 = (null: string __withnull) |> f3 // Expect to give a warning
+    check "ekjnceoiwew4" w4 1
+
+module MemberBasics = 
+    type C() = 
+        member x.P = 1
+        member x.M() = 2
+
+    let c : C __withnull = C()
+    let v1 = c.P  // Expected to give a warning
+    check "ekjnccwwecv1" v1 1
+    let v2 = c.M()  // Expected to give a warning
+    check "ekjnccwwecv2" v2 2
+    let f1 = c.M  // Expected to give a warning
+    check "ekjnccwwecv3" (f1()) 2
+
+module Basics2 = 
+    let f1 () = null
+    // val f : unit -> 'a when 'a : null
+
+    let f2 () : string __withnull = null
+    // val f : unit -> string __withnull
+
+    let f3 () : 'T __withnull = null
+
+    let f4 () : 'T __withnull when 'T : not struct = null
+
+    let f5 () : 'T when 'T : not struct and 'T : null = null
+
+#if NEGATIVE
+    let f6 () : 'T __withnull when 'T : not struct and 'T : null = null // Expected to give an error about inconistent constraints
+#endif
+
+    // Note yet allowed 
+    //let f7 () : 'T __withnull when 'T : struct = null
+    let f7b () : Nullable<'T> = nullV // BUG: Incorrectly gives a warning about System.ValueType with /test:AssumeNullOnImport
+
+    let f8 () : string = null // Expected to give a Nullness warning
+
+type C(s: string) = 
+    member __.Value = s
+
+module InteropBasics =
+    let s0 = String.Concat("a","b") // Expected to infer string __withnull with /test:AssumeNullOnImport
+    check "ekjnccberpos0" s0 "ab"
+    let s1 : string = String.Concat("a","c") // Expected to gives a warning with /test:AssumeNullOnImport
+    check "ekjnccberpos0" s1 "ac"
+    let test1()  = String.Concat("a","d")
+    check "ekjnccberpos0" (test1()) "ad"
+    let test2(s1:string, s2: string)  = String.Concat(s1,s2)
+    let test3()  = String( [| 'a' |] )
+    let test4()  = System.AppDomain.CurrentDomain
+    let test5 : System.AppDomain  = System.AppDomain.CurrentDomain // Expected to gives a warning with /test:AssumeNullOnImport
+
+type KonsoleWithNulls = 
+    static member WriteLine(s: string __withnull) = Console.WriteLine(s)
+    static member WriteLine(fmt: string __withnull, arg1: string __withnull) = Console.WriteLine(fmt, arg1)
+    static member WriteLine(fmt: string __withnull, [] args: obj __withnull[] __withnull) = Console.WriteLine(fmt, args)
+    static member WriteLineC(s: C __withnull) = Console.WriteLine(s.Value)
+    static member WriteLineC(fmt: C __withnull, arg1: C __withnull) = Console.WriteLine(fmt.Value, arg1.Value)
+
+module KonsoleWithNullsModule = 
+    let WriteLine(s: string __withnull) = Console.WriteLine(s)
+    let WriteLine2(fmt: string __withnull, arg1: string __withnull) = Console.WriteLine(fmt, arg1)
+    let WriteLineC(s: C __withnull) = Console.WriteLine(s.Value)
+    let WriteLineC2(fmt: C __withnull, arg1: C __withnull) = Console.WriteLine(fmt.Value, arg1.Value)
+
+module KonsoleWithNullsModule2 = 
+    let WriteLine x = KonsoleWithNullsModule.WriteLine x
+    let WriteLine2 (fmt, arg1) = KonsoleWithNullsModule.WriteLine2(fmt, arg1)
+    let WriteLineC(s) = KonsoleWithNullsModule.WriteLineC(s)
+    let WriteLineC2(fmt, arg1) = KonsoleWithNullsModule.WriteLineC2(fmt, arg1)
+
+type KonsoleNoNulls = 
+    static member WriteLine(s: string) = Console.WriteLine(s)
+    static member WriteLine(fmt: string, arg1: string __withnull) = Console.WriteLine(fmt, arg1)
+    static member WriteLine(fmt: string, [] args: obj[]) = Console.WriteLine(fmt, args)
+    static member WriteLineC(s: C) = Console.WriteLine(s.Value)
+    static member WriteLineC(fmt: C, arg1: C) = Console.WriteLine(fmt.Value, arg1.Value)
+
+module KonsoleNoNullsModule = 
+    let WriteLine(s: string) = Console.WriteLine(s)
+    let WriteLine2(fmt: string, arg1: string) = Console.WriteLine(fmt, arg1)
+    let WriteLineC(s: C) = Console.WriteLine(s.Value)
+    let WriteLineC2(fmt: C, arg1: C) = Console.WriteLine(fmt.Value, arg1.Value)
+
+module KonsoleNoNullsModule2 = 
+    let WriteLine x = KonsoleNoNullsModule.WriteLine x
+    let WriteLine2 (fmt, arg1) = KonsoleNoNullsModule.WriteLine2(fmt, arg1)
+    let WriteLineC(s) = KonsoleNoNullsModule.WriteLineC(s)
+    let WriteLineC2(fmt, arg1) = KonsoleNoNullsModule.WriteLineC2(fmt, arg1)
+
+System.Console.WriteLine("a")
+System.Console.WriteLine("a", (null: obj[])) // Expected to give a Nullness warning
+
+KonsoleWithNulls.WriteLine("Hello world")
+KonsoleWithNulls.WriteLine(null) // WRONG: gives an incorrect Nullness warning for string __withnull and string __withnull
+KonsoleWithNulls.WriteLine("Hello","world")
+KonsoleWithNulls.WriteLine("Hello","world","there") // // WRONG: gives an incorrect Nullness warning for string __withnull and string __withnull
+
+KonsoleNoNulls.WriteLine("Hello world")
+try 
+   KonsoleNoNulls.WriteLine(null)  // Expected to give a Nullness warning
+with :? System.ArgumentNullException -> ()
+KonsoleNoNulls.WriteLine("Hello","world")
+//KonsoleNoNulls.WriteLine("Hello",null) // CHECK ME 
+try 
+    KonsoleNoNulls.WriteLine(null, "World")   // Expected to give a Nullness warning
+with :? System.ArgumentNullException -> ()
+
+KonsoleWithNullsModule.WriteLine("Hello world")
+try 
+    KonsoleWithNullsModule.WriteLine(null) 
+with :? System.ArgumentNullException -> ()
+KonsoleWithNullsModule.WriteLine2("Hello","world") 
+KonsoleWithNullsModule.WriteLine2("Hello",null)
+try
+    KonsoleWithNullsModule.WriteLine2(null,"world")
+with :? System.ArgumentNullException -> ()
+
+KonsoleWithNullsModule2.WriteLine("Hello world")
+try 
+    KonsoleWithNullsModule2.WriteLine(null) 
+with :? System.ArgumentNullException -> ()
+KonsoleWithNullsModule2.WriteLine2("Hello","world")
+KonsoleWithNullsModule2.WriteLine2("Hello",null)
+try 
+    KonsoleWithNullsModule2.WriteLine2(null,"world")
+with :? System.ArgumentNullException -> ()
+
+KonsoleNoNullsModule.WriteLine("Hello world")
+try 
+    KonsoleNoNullsModule.WriteLine(null)  // Expected to give a Nullness warning
+with :? System.ArgumentNullException -> ()
+KonsoleNoNullsModule.WriteLine2("Hello","world")
+KonsoleNoNullsModule.WriteLine2("Hello",null) // Expected to give a Nullness warning
+try 
+    KonsoleNoNullsModule.WriteLine2(null,"world") // Expected to give a Nullness warning
+with :? System.ArgumentNullException -> ()
+
+//-------------------------------------
+
+// Param array cases
+
+KonsoleNoNulls.WriteLine("Hello","world","there")
+KonsoleWithNulls.WriteLine("Hello","world",null)  // Expected to give a Nullness warning 
+KonsoleNoNulls.WriteLine("Hello","world",null)  // Expected to give a Nullness warning
+System.Console.WriteLine("a", (null: obj[] __withnull)) 
+System.Console.WriteLine("a", (null: obj __withnull[] __withnull))
+
+//-------
+// random stuff
+
+let f0 line = 
+    let add (s:string) = ()
+    match line with 
+    | null | "" -> ()
+    | _ -> add line // Exected to give a nullness warning
+
+let f0b line = 
+    let add (s:string) = ()
+    match line with 
+    | null  -> ()
+    | _ -> add (nonNull line) // Exected to give a nullness warning
+
+let add (s:string) = ()
+let f0c line = 
+    add (nonNull "") // WRONG: should not give a nullness warning
+
+//let f2 (x: string or null) = x;;
+let f3 (x: string __withnull) = x
+let f5 x = (x: int)
+//let f4 x = (x: string nullable)
+
+//let f6<'T when 'T : __notnull> (x: 'T) = x
+//let f6<'T when 'T : __notnull> (x: 'T) = x
+
+//let f2 (x: string | null) = x;;
+
+//let f2 (_x : string | null) = x;;
+
+//let f2 (x: (string | null)) = x;;
+
+//let f3 x = (x: (string | null))
+
+module NullConstraintTests =
+    type C<'T when 'T : null>() = class end
+
+#if NEGATIVE
+    let f1 (y : C< (int * int) >) = y // This gave an error in F# 4.5 and we expect it to continue to give an error
+
+#endif
+
+#if CHECKNULLS
+     // This gave an error in F# 4.5.  It now only gives a warning when --checknulls is on which is sort of ok
+     // since we are treating .NET and F# types more symmetrically.
+     //
+     // TODO: However it gives no error or warning at all with --checknulls off in F# 5.0...  That seems bad.
+    let f2 (y : C) = y
+
+    let f3 (y : C) = y // Expect a Nullness warning
+
+    let f4 (y : C) = y // No warning expected 
+
+    let f5 (y : C) = y // No warning expected
+
+    let f6 (y : C __withnull>) = y // No warning expected, lexing/parsing should succeed 
+
+    let f7 (y : C> __withnull) = y // No warning expected, lexing/parsing should succeed
+#endif
+
+
+module DefaultValueTests =
+
+
+    module StructExamples = 
+        []
+        type C1 =
+            []
+            val mutable Whoops : string // expect a warning
+
+        []
+        type C2 =
+            []
+            val mutable Whoops : string // expect no warning
+
+        []
+        type C3 =
+            []
+            val mutable Whoops : string __withnull // expect no warning
+
+#if NEGATIVE
+        []
+        type C4a =
+            []
+            val mutable Whoops : int list // expect a hard error like in F# 4.5
+#endif
+
+        []
+        type C4b =
+            []
+            val mutable Whoops : int list __withnull // expect no warning
+
+#if NEGATIVE
+        []
+        type C5 =
+            []
+            val mutable Whoops : int * int // expect an error like F# 4.5
+
+        []
+        type C6 =
+            []
+            val mutable Whoops : int -> int // expect an error like F# 4.5
+#endif
+
+        []
+        type C7 =
+            []
+            val mutable Whoops : (int -> int) __withnull // expect no warning
+
+    module ClassExamples = 
+        type C1 =
+            []
+            val mutable Whoops : string // expect a warning
+
+        type C2 =
+            []
+            val mutable Whoops : string // expect no warning
+
+        type C3 =
+            []
+            val mutable Whoops : string __withnull // expect no warning
+
+        type C4a =
+            []
+            val mutable Whoops : int list // ** expect a warning
+
+        type C4b =
+            []
+            val mutable Whoops : int list __withnull // expect no warning
+
+    #if NEGATIVE
+        type C5 =
+            []
+            val mutable Whoops : int * int // expect an error like F# 4.5
+
+        type C6 =
+            []
+            val mutable Whoops : int -> int // expect an error like F# 4.5
+    #endif
+
+        type C7 =
+            []
+            val mutable Whoops : (int -> int) __withnull // expect no warning
+*)
+

From 208c48d36164636171d4e62153633e2d47876375 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Wed, 24 May 2023 20:56:07 +0100
Subject: [PATCH 03/59] move adhoc tests and clean errors

---
 FSharpBuild.Directory.Build.props             |   5 +-
 VisualFSharp.sln                              |   2 +-
 src/Compiler/Checking/CheckDeclarations.fs    |   1 -
 src/Compiler/Checking/CheckExpressions.fs     |   4 +-
 src/Compiler/Checking/CheckPatterns.fs        |   2 -
 src/Compiler/Checking/ConstraintSolver.fs     | 189 +++-----
 src/Compiler/Checking/ConstraintSolver.fsi    |   6 +-
 src/Compiler/Checking/MethodCalls.fs          |   6 +-
 src/Compiler/Checking/NicePrint.fs            |  45 +-
 src/Compiler/Checking/PostInferenceChecks.fs  |  19 +-
 src/Compiler/Driver/CompilerDiagnostics.fs    |  30 +-
 src/Compiler/FSComp.txt                       |  12 +-
 src/Compiler/FSStrings.resx                   |  10 +-
 src/Compiler/Symbols/SymbolHelpers.fs         |   1 +
 src/Compiler/TypedTree/TypedTreeOps.fs        |  23 +-
 src/Compiler/TypedTree/TypedTreeOps.fsi       |  11 +-
 tests/adhoc/nullness/enabled/negative.fs      |   5 +
 tests/adhoc/nullness/enabled/positive.fs      | 280 +++++++++++
 .../adhoc/nullness/enabled/positive.next.bsl  |  16 +
 .../enabled/positive.next.enabled.bsl         |  18 +
 .../positive.next.enabled.checknulls.bsl      |  70 +++
 tests/adhoc/nullness/existing/negative.fs     | 107 +++++
 .../adhoc/nullness/existing/negative.next.bsl |   4 +
 .../existing/negative.next.enabled.bsl        |   4 +
 .../negative.next.enabled.checknulls.bsl      |  14 +
 .../nullness/existing/negative.previous.bsl   |   4 +
 tests/adhoc/nullness/existing/positive.fs     |  89 ++++
 .../adhoc/nullness/existing/positive.next.bsl |   0
 .../existing/positive.next.enabled.bsl        |   0
 .../positive.next.enabled.checknulls.bsl      |  18 +
 .../nullness/existing/positive.previous.bsl   |   0
 tests/adhoc/nullness/interop/positive.fs      |  18 +
 tests/adhoc/nullness/library/positive.fs      |  75 +++
 tests/adhoc/nullness/micro.fs                 |   9 +
 tests/adhoc/nullness/micro.fsi                |   3 +
 .../core => adhoc}/nullness/nullness.fsproj   |   7 +-
 tests/adhoc/nullness/validate.cmd             |  35 ++
 tests/fsharp/core/nullness/test.fsx           | 450 ------------------
 38 files changed, 912 insertions(+), 680 deletions(-)
 create mode 100644 tests/adhoc/nullness/enabled/negative.fs
 create mode 100644 tests/adhoc/nullness/enabled/positive.fs
 create mode 100644 tests/adhoc/nullness/enabled/positive.next.bsl
 create mode 100644 tests/adhoc/nullness/enabled/positive.next.enabled.bsl
 create mode 100644 tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl
 create mode 100644 tests/adhoc/nullness/existing/negative.fs
 create mode 100644 tests/adhoc/nullness/existing/negative.next.bsl
 create mode 100644 tests/adhoc/nullness/existing/negative.next.enabled.bsl
 create mode 100644 tests/adhoc/nullness/existing/negative.next.enabled.checknulls.bsl
 create mode 100644 tests/adhoc/nullness/existing/negative.previous.bsl
 create mode 100644 tests/adhoc/nullness/existing/positive.fs
 create mode 100644 tests/adhoc/nullness/existing/positive.next.bsl
 create mode 100644 tests/adhoc/nullness/existing/positive.next.enabled.bsl
 create mode 100644 tests/adhoc/nullness/existing/positive.next.enabled.checknulls.bsl
 create mode 100644 tests/adhoc/nullness/existing/positive.previous.bsl
 create mode 100644 tests/adhoc/nullness/interop/positive.fs
 create mode 100644 tests/adhoc/nullness/library/positive.fs
 create mode 100644 tests/adhoc/nullness/micro.fs
 create mode 100644 tests/adhoc/nullness/micro.fsi
 rename tests/{fsharp/core => adhoc}/nullness/nullness.fsproj (78%)
 create mode 100644 tests/adhoc/nullness/validate.cmd
 delete mode 100644 tests/fsharp/core/nullness/test.fsx

diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props
index d0b155bb410..7e13aa95e13 100644
--- a/FSharpBuild.Directory.Build.props
+++ b/FSharpBuild.Directory.Build.props
@@ -112,12 +112,9 @@
   
 
   
-  
-  
 
diff --git a/VisualFSharp.sln b/VisualFSharp.sln
index 516513595da..94d3cef1d10 100644
--- a/VisualFSharp.sln
+++ b/VisualFSharp.sln
@@ -195,7 +195,7 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Editor.Tests", "vsin
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FSharp.Editor.IntegrationTests", "vsintegration\tests\FSharp.Editor.IntegrationTests\FSharp.Editor.IntegrationTests.csproj", "{E31F9B59-FCF1-4D04-8762-C7BB60285A7B}"
 EndProject
-Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "nullness", "tests\fsharp\core\nullness\nullness.fsproj", "{6992D926-AB1C-4CD4-94D5-0319D14DB54B}"
+Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "nullness", "tests\adhoc\nullness\nullness.fsproj", "{6992D926-AB1C-4CD4-94D5-0319D14DB54B}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs
index 3c97ea8354e..c5d80fad012 100644
--- a/src/Compiler/Checking/CheckDeclarations.fs
+++ b/src/Compiler/Checking/CheckDeclarations.fs
@@ -3211,7 +3211,6 @@ module EstablishTypeDefinitionCores =
                     tycon.TypeContents.tcaug_super |> Option.iter (fun ty -> if not (TypeNullIsExtraValue g m ty) then errorR (Error(FSComp.SR.tcAllowNullTypesMayOnlyInheritFromAllowNullTypes(), m)))
                     tycon.ImmediateInterfaceTypesOfFSharpTycon |> List.iter (fun ty -> if not (TypeNullIsExtraValue g m ty) then errorR (Error(FSComp.SR.tcAllowNullTypesMayOnlyInheritFromAllowNullTypes(), m)))
                 
-                
             let structLayoutAttributeCheck allowed = 
                 let explicitKind = int32 System.Runtime.InteropServices.LayoutKind.Explicit
                 match structLayoutAttr with
diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs
index 666c8acc1a9..f53b7c07c3c 100644
--- a/src/Compiler/Checking/CheckExpressions.fs
+++ b/src/Compiler/Checking/CheckExpressions.fs
@@ -4000,7 +4000,7 @@ let rec TcTyparConstraint ridx (cenv: cenv) newOk checkConstraints occ (env: TcE
         tpenv
 
     | SynTypeConstraint.WhereTyparSupportsNull(tp, m) ->
-        TcSimpleTyparConstraint cenv env newOk tpenv tp m AddCxTypeDefnSupportsNull
+        TcSimpleTyparConstraint cenv env newOk tpenv tp m AddCxTypeUseSupportsNull
 
     | SynTypeConstraint.WhereTyparNotSupportsNull(tp, m) ->
         if g.langFeatureNullness then 
@@ -5615,9 +5615,7 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE
 
     | SynExpr.Null m ->
         TcNonControlFlowExpr env <| fun env ->
-        // Which?
         AddCxTypeUseSupportsNull env.DisplayEnv cenv.css m NoTrace overallTy.Commit
-        //AddCxTypeDefnSupportsNull env.DisplayEnv cenv.css m NoTrace overallTy.Commit
         let tyWithNull = addNullnessToTy KnownWithNull overallTy.Commit
         mkNull m tyWithNull, tpenv
 
diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs
index 2c28dfb5110..5ce9fa02e69 100644
--- a/src/Compiler/Checking/CheckPatterns.fs
+++ b/src/Compiler/Checking/CheckPatterns.fs
@@ -461,8 +461,6 @@ and TcRecordPat warnOnUpper cenv env vFlags patEnv ty fieldPats m =
 and TcNullPat cenv env patEnv ty m =
     try
         AddCxTypeUseSupportsNull env.DisplayEnv cenv.css m NoTrace ty
-        // Which?
-        //AddCxTypeDefnSupportsNull env.DisplayEnv cenv.css m NoTrace ty
     with exn ->
         errorRecovery exn m
     (fun _ -> TPat_null m), patEnv
diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs
index 2cd52880800..40f7747e3a2 100644
--- a/src/Compiler/Checking/ConstraintSolver.fs
+++ b/src/Compiler/Checking/ConstraintSolver.fs
@@ -253,7 +253,7 @@ exception ConstraintSolverNullnessWarningWithTypes of DisplayEnv * TType * TType
 
 exception ConstraintSolverNullnessWarningWithType of DisplayEnv * TType * NullnessInfo * range  * range 
 
-exception ConstraintSolverNonNullnessWarningWithType of DisplayEnv * TType * NullnessInfo * range  * range 
+exception ConstraintSolverNullnessWarning of string * range * range 
 
 exception ConstraintSolverError of string * range * range
 
@@ -1056,8 +1056,8 @@ and SolveTypMeetsTyparConstraints (csenv: ConstraintSolverEnv) ndeep m2 trace ty
               | ValueSome destTypar ->
                   AddConstraint csenv ndeep m2 trace destTypar (TyparConstraint.DefaultsTo(priority, dty, m))
           
-      | TyparConstraint.NotSupportsNull m2             -> SolveTypeDefnNotSupportsNull        csenv ndeep m2 trace ty
-      | TyparConstraint.SupportsNull m2                -> SolveTypeDefnSupportsNull           csenv ndeep m2 trace ty
+      | TyparConstraint.NotSupportsNull m2             -> SolveTypeUseNotSupportsNull         csenv ndeep m2 trace ty
+      | TyparConstraint.SupportsNull m2                -> SolveTypeUseSupportsNull            csenv ndeep m2 trace ty
       | TyparConstraint.IsEnum(underlyingTy, m2)       -> SolveTypeIsEnum                     csenv ndeep m2 trace ty underlyingTy
       | TyparConstraint.SupportsComparison(m2)         -> SolveTypeSupportsComparison         csenv ndeep m2 trace ty
       | TyparConstraint.SupportsEquality(m2)           -> SolveTypeSupportsEquality           csenv ndeep m2 trace ty
@@ -1100,7 +1100,7 @@ and SolveNullnessEquiv (csenv:ConstraintSolverEnv) m2 (trace: OptionalTrace) ty1
         | _ -> 
             // NOTE: we never give nullness warnings for the 'obj' type
             if csenv.g.checkNullness then 
-                if not (isObjTy csenv.g ty1) && not (isObjTy csenv.g ty2) then 
+                if not (isObjTy csenv.g ty1) || not (isObjTy csenv.g ty2) then 
                     WarnD(ConstraintSolverNullnessWarningEquivWithTypes(csenv.DisplayEnv, ty1, ty2, n1, n2, csenv.m, m2)) 
                 else
                     CompleteD
@@ -1133,7 +1133,7 @@ and SolveNullnessSubsumesNullness (csenv:ConstraintSolverEnv) m2 (trace: Optiona
         | NullnessInfo.WithNull, NullnessInfo.WithoutNull -> CompleteD
         | NullnessInfo.WithoutNull, NullnessInfo.WithNull -> 
             if csenv.g.checkNullness then 
-                if not (isObjTy csenv.g ty1) && not (isObjTy csenv.g ty2) then 
+                if not (isObjTy csenv.g ty1) || not (isObjTy csenv.g ty2) then 
                     WarnD(ConstraintSolverNullnessWarningWithTypes(csenv.DisplayEnv, ty1, ty2, n1, n2, csenv.m, m2)) 
                 else
                     CompleteD
@@ -2457,7 +2457,47 @@ and AddConstraint (csenv: ConstraintSolverEnv) ndeep m2 trace tp newConstraint
             ()
     }
 
-and SolveNullnessSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) ty nullness = trackErrors {
+// This version prefers to constrain the nullness annotation for a type annotation usage
+and SolveTypeUseSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 trace ty = trackErrors {
+    let g = csenv.g
+    let m = csenv.m
+    let denv = csenv.DisplayEnv
+    if g.langFeatureNullness then 
+        if TypeNullIsExtraValueNew g m ty then 
+            ()
+        elif isNullableTy g ty then
+            return! ErrorD (ConstraintSolverError(FSComp.SR.csNullableTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2))
+        else
+            match tryDestTyparTy g ty with
+            | ValueSome tp ->
+                do! SolveTypeIsReferenceType csenv ndeep m2 trace ty
+                let nullness = nullnessOfTy g ty
+                match nullness.TryEvaluate() with
+                | ValueSome NullnessInfo.WithoutNull ->
+                    return! AddConstraint csenv ndeep m2 trace tp (TyparConstraint.SupportsNull m)
+                | _ ->
+                    return! SolveNullnessSupportsNull csenv ndeep m2 trace ty nullness
+            | _ ->
+                let nullness = nullnessOfTy g ty
+                do! SolveNullnessSupportsNull csenv ndeep m2 trace ty nullness
+
+                // If checkNullness is off give the same errors as F# 4.5
+                if not g.checkNullness && not (TypeNullIsExtraValue g m ty) then
+                    return! ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2))
+    else
+        if TypeNullIsExtraValue g m ty then
+            ()
+        elif isNullableTy g ty then
+            return! ErrorD (ConstraintSolverError(FSComp.SR.csNullableTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2))
+        else
+            match tryDestTyparTy g ty with
+            | ValueSome tp ->
+                do! AddConstraint csenv ndeep m2 trace tp (TyparConstraint.SupportsNull m)
+            | ValueNone ->
+                return! ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2))
+    }
+
+and SolveNullnessSupportsNull (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) ty nullness = trackErrors {
     let g = csenv.g
     let m = csenv.m
     let denv = csenv.DisplayEnv
@@ -2472,87 +2512,32 @@ and SolveNullnessSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 (trace: Optio
         | NullnessInfo.AmbivalentToNull -> ()
         | NullnessInfo.WithNull -> ()
         | NullnessInfo.WithoutNull -> 
-            if g.checkNullness then 
-                if not (isObjTy g ty) then 
-                    return! WarnD(ConstraintSolverNullnessWarningWithType(denv, ty, n1, m, m2)) 
+            if g.checkNullness && not (isObjTy g ty) then 
+                return! WarnD(ConstraintSolverNullnessWarningWithType(denv, ty, n1, m, m2)) 
   }
 
-and SolveTypeSupportsNullCore (csenv:ConstraintSolverEnv) ndeep m2 trace ty = trackErrors {
+and SolveTypeUseNotSupportsNull (csenv: ConstraintSolverEnv) ndeep m2 trace ty = trackErrors {
     let g = csenv.g
     let m = csenv.m
     let denv = csenv.DisplayEnv
-    if TypeNullIsExtraValueNew g m ty then 
-        ()
-    else
-        match ty with 
-        | NullableTy g _ ->
-            return! ErrorD (ConstraintSolverError(FSComp.SR.csNullableTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2))
-        | _ -> 
-            // If langFeatureNullness is on then solve, maybe give warnings
-            if g.langFeatureNullness then 
-                let nullness = nullnessOfTy g ty
-                do! SolveNullnessSupportsNull csenv ndeep m2 trace ty nullness
-
-            // If langFeatureNullness or checkNullness are off give the same errors as F# 4.5
-            if not g.langFeatureNullness || not g.checkNullness then 
-                if not (TypeNullIsExtraValue g m ty) then
-                    return! ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2))
-  }
 
-// This version prefers to constrain a type parameter definiton
-and SolveTypeDefnSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 trace ty =
-    let g = csenv.g
-    let m = csenv.m
-    let denv = csenv.DisplayEnv
-    if g.langFeatureNullness then 
-        match stripTyparEqns ty with 
-        // If you set a type variable constrained with a T: null to U? then you don't induce an inference constraint
-        // of U: null.
-        // TODO: what about Obsolete?
-        | TType_var(_, nullness) when nullness.Evaluate() = NullnessInfo.WithNull -> CompleteD
-        | _ ->
-        match tryDestTyparTy g ty with
-        | ValueSome tp ->
-            AddConstraint csenv ndeep m2 trace tp (TyparConstraint.SupportsNull m)
-        | ValueNone ->
-            SolveTypeSupportsNullCore csenv ndeep m2 trace ty
-    else
-        match tryDestTyparTy g ty with
-        | ValueSome destTypar ->
-            AddConstraint csenv ndeep m2 trace destTypar (TyparConstraint.SupportsNull m)
-        | ValueNone ->
-            if TypeNullIsExtraValue g m ty then CompleteD else 
-            match ty with 
-            | NullableTy g _ ->
-                ErrorD (ConstraintSolverError(FSComp.SR.csNullableTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2))
-            | _ -> 
-                ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2))
-    
-// This version prefers to constrain the nullness annotation for a type annotation usage
-and SolveTypeUseSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 trace ty =
-    let g = csenv.g
-    let m = csenv.m
-    let denv = csenv.DisplayEnv
-    if g.langFeatureNullness then 
-        match stripTyparEqns ty with 
-        | TType_var(tp, nullness) ->
-            AddConstraint csenv ndeep m2 trace tp (TyparConstraint.IsReferenceType m) ++ (fun () -> 
-            SolveNullnessSupportsNull csenv ndeep m2 trace ty nullness)
-        | _ ->
-            SolveTypeSupportsNullCore csenv ndeep m2 trace ty
+    if TypeNullIsTrueValue g ty then 
+        // We can only give warnings here as F# 5.0 introduces these constraints into existing
+        // code via Option.ofObj and Option.toObj
+        do! WarnD (ConstraintSolverNullnessWarning(FSComp.SR.csTypeHasNullAsTrueValue(NicePrint.minimalStringOfType denv ty), m, m2))
+    elif TypeNullIsExtraValueNew g m ty then 
+        if g.checkNullness && not (isObjTy g ty) then 
+            do! WarnD (ConstraintSolverNullnessWarning(FSComp.SR.csTypeHasNullAsExtraValue(NicePrint.minimalStringOfType denv ty), m, m2))
     else
         match tryDestTyparTy g ty with
-        | ValueSome destTypar ->
-            AddConstraint csenv ndeep m2 trace destTypar (TyparConstraint.SupportsNull m)
+        | ValueSome tp ->
+            do! AddConstraint csenv ndeep m2 trace tp (TyparConstraint.NotSupportsNull m)
         | ValueNone ->
-            if TypeNullIsExtraValue g m ty then CompleteD else 
-            match ty with 
-            | NullableTy g _ ->
-                ErrorD (ConstraintSolverError(FSComp.SR.csNullableTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2))
-            | _ -> 
-                ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotHaveNull(NicePrint.minimalStringOfType denv ty), m, m2))
+            let nullness = nullnessOfTy g ty
+            do! SolveNullnessNotSupportsNull csenv ndeep m2 trace ty nullness
+  }
 
-and SolveNullnessNotSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) ty nullness = trackErrors {
+and SolveNullnessNotSupportsNull (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) ty nullness = trackErrors {
     let g = csenv.g
     let m = csenv.m
     let denv = csenv.DisplayEnv
@@ -2567,47 +2552,10 @@ and SolveNullnessNotSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 (trace: Op
         | NullnessInfo.AmbivalentToNull -> ()
         | NullnessInfo.WithoutNull -> ()
         | NullnessInfo.WithNull -> 
-            if g.checkNullness then 
-                if not (isObjTy g ty) then 
-                    return! WarnD(ConstraintSolverNonNullnessWarningWithType(denv, ty, n1, m, m2)) 
-            else
-                if TypeNullIsExtraValue g m ty then
-                    return! ErrorD (ConstraintSolverError(FSComp.SR.csTypeHasNullAsExtraValue(NicePrint.minimalStringOfType denv ty), m, m2))
+            if g.checkNullness && TypeNullIsExtraValueNew g m ty && not (isObjTy g ty) then
+                return! WarnD(ConstraintSolverNullnessWarning(FSComp.SR.csTypeHasNullAsExtraValue(NicePrint.minimalStringOfType denv ty), m, m2))
   }
 
-and SolveTypeNotSupportsNullCore (csenv:ConstraintSolverEnv) ndeep m2 trace ty = trackErrors {
-    let g = csenv.g
-    let m = csenv.m
-    let denv = csenv.DisplayEnv
-    if TypeNullIsTrueValue g ty then 
-        // We can only give warnings here as F# 5.0 introduces these constraints into existing
-        // code via Option.ofObj and Option.toObj
-        do! WarnD (ConstraintSolverError(FSComp.SR.csTypeHasNullAsTrueValue(NicePrint.minimalStringOfType denv ty), m, m2))
-    elif TypeNullIsExtraValueNew g m ty then 
-        if g.checkNullness || TypeNullIsExtraValue g m ty then 
-            do! WarnD (ConstraintSolverError(FSComp.SR.csTypeHasNullAsExtraValue(NicePrint.minimalStringOfType denv ty), m, m2))
-    else
-        if g.checkNullness then 
-            let nullness = nullnessOfTy g ty
-            do! SolveNullnessNotSupportsNull csenv ndeep m2 trace ty nullness
-  }
-
-// This version prefers to constrain a type parameter definiton
-and SolveTypeDefnNotSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 trace ty =
-    let g = csenv.g
-    let m = csenv.m
-    //match stripTyparEqns ty with 
-    //// If you set a type variable constrained with a T: __notnull to U then you don't induce an inference constraint
-    //// of U: __notnull.
-    //// TODO: what about Obsolete?
-    //| TType_var(_, nullness) when nullness.TryEvaluate() = Some NullnessInfo.WithoutNull || nullness.TryEvaluate() = Some NullnessInfo.AmbivalentToNull -> CompleteD
-    //| _ ->
-    match tryDestTyparTy g ty with
-    | ValueSome tp ->
-        AddConstraint csenv ndeep m2 trace tp (TyparConstraint.NotSupportsNull m)
-    | ValueNone ->
-        SolveTypeNotSupportsNullCore csenv ndeep m2 trace ty
-
 and SolveTypeSupportsComparison (csenv: ConstraintSolverEnv) ndeep m2 trace ty =
     let g = csenv.g
     let m = csenv.m
@@ -3844,17 +3792,10 @@ let AddCxMethodConstraint denv css m trace traitInfo  =
         (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m)))
     |> RaiseOperationResult
 
-let AddCxTypeDefnSupportsNull denv css m trace ty =
-    let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv
-    PostponeOnFailedMemberConstraintResolution csenv trace
-        (fun csenv -> SolveTypeDefnSupportsNull csenv 0 m trace ty)
-        (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m)))
-    |> RaiseOperationResult
-
 let AddCxTypeDefnNotSupportsNull denv css m trace ty =
     let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv
     PostponeOnFailedMemberConstraintResolution csenv trace
-        (fun csenv -> SolveTypeDefnNotSupportsNull csenv 0 m trace ty)
+        (fun csenv -> SolveTypeUseNotSupportsNull csenv 0 m trace ty)
         (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m)))
     |> RaiseOperationResult
 
diff --git a/src/Compiler/Checking/ConstraintSolver.fsi b/src/Compiler/Checking/ConstraintSolver.fsi
index a0943c752bf..938fab222c6 100644
--- a/src/Compiler/Checking/ConstraintSolver.fsi
+++ b/src/Compiler/Checking/ConstraintSolver.fsi
@@ -193,7 +193,9 @@ exception ConstraintSolverNullnessWarningWithTypes of
     range
 
 exception ConstraintSolverNullnessWarningWithType of DisplayEnv * TType * NullnessInfo * range * range
-exception ConstraintSolverNonNullnessWarningWithType of DisplayEnv * TType * NullnessInfo * range * range
+
+exception ConstraintSolverNullnessWarning of string * range * range
+
 exception ConstraintSolverError of string * range * range
 
 exception ErrorFromApplyingDefault of
@@ -318,8 +320,6 @@ val AddCxMethodConstraint: DisplayEnv -> ConstraintSolverState -> range -> Optio
 
 val AddCxTypeDefnNotSupportsNull: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit
 
-val AddCxTypeDefnSupportsNull: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit
-
 val AddCxTypeUseSupportsNull: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit
 
 val AddCxTypeMustSupportComparison: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit
diff --git a/src/Compiler/Checking/MethodCalls.fs b/src/Compiler/Checking/MethodCalls.fs
index e8d6850bc77..322aa43c53a 100644
--- a/src/Compiler/Checking/MethodCalls.fs
+++ b/src/Compiler/Checking/MethodCalls.fs
@@ -1183,11 +1183,9 @@ let BuildMethodCall tcVal g amap isMutable m isProp minfo valUseFlags minst objA
 
         // Build a 'call' to a struct default constructor 
         | DefaultStructCtor (g, ty) -> 
-            if g.langFeatureNullness then 
-                if not (TypeHasDefaultValueNew g m ty) && not (TypeHasDefaultValue g m ty) then 
+            if g.langFeatureNullness && g.checkNullness then
+                if not (TypeHasDefaultValueNew g m ty) then 
                     errorR(Error(FSComp.SR.tcDefaultStructConstructorCall(), m))
-                if g.checkNullness && not (TypeHasDefaultValueNew g m ty) then 
-                    warning(Error(FSComp.SR.tcDefaultStructConstructorCallNulls(), m))  
             else
                 if not (TypeHasDefaultValue g m ty) then 
                     errorR(Error(FSComp.SR.tcDefaultStructConstructorCall(), m))
diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs
index 21196099f96..7412023285c 100644
--- a/src/Compiler/Checking/NicePrint.fs
+++ b/src/Compiler/Checking/NicePrint.fs
@@ -878,11 +878,14 @@ module PrintTypes =
             | [arg] -> layoutTypeWithInfoAndPrec denv env 2 arg ^^ tcL
             | args -> bracketIfL (prec <= 1) (bracketL (layoutTypesWithInfoAndPrec denv env 2 (sepL (tagPunctuation ",")) args) --- tcL)
 
-    and layoutNullness part2 (nullness: Nullness) =
-        match nullness.Evaluate() with
-        | NullnessInfo.WithNull -> part2 ^^ wordL (tagText "__withnull")
-        | NullnessInfo.WithoutNull -> part2
-        | NullnessInfo.AmbivalentToNull -> part2 ^^ wordL (tagText "__maybenull")  // TODO NULLNESS: emit this optionally ^^ wordL (tagText "%")
+    and layoutNullness (denv: DisplayEnv) part2 (nullness: Nullness) =
+        if denv.showNullnessAnnotations then
+            match nullness.Evaluate() with
+            | NullnessInfo.WithNull -> part2 ^^ wordL (tagText "__withnull")
+            | NullnessInfo.WithoutNull -> part2
+            | NullnessInfo.AmbivalentToNull -> part2 //^^ wordL (tagText "__maybenull")
+        else
+            part2
     
     /// Layout a type, taking precedence into account to insert brackets where needed
     and layoutTypeWithInfoAndPrec denv env prec ty =
@@ -903,13 +906,18 @@ module PrintTypes =
 
         // Always prefer 'float' to 'float<1>'
         | TType_app (tc, args, _) when tc.IsMeasureableReprTycon && List.forall (isDimensionless g) args ->
-          layoutTypeWithInfoAndPrec denv env prec (reduceTyconRefMeasureableOrProvided g tc args)
+            layoutTypeWithInfoAndPrec denv env prec (reduceTyconRefMeasureableOrProvided g tc args)
 
         // Layout a type application
-        | TType_ucase (UnionCaseRef(tc, _), args)
-        | TType_app (tc, args, _) ->
-          let prefix = usePrefix denv tc
-          layoutTypeAppWithInfoAndPrec denv env (layoutTyconRef denv tc) prec prefix args
+        | TType_ucase (UnionCaseRef(tc, _), args) ->
+            let prefix = usePrefix denv tc
+            layoutTypeAppWithInfoAndPrec denv env (layoutTyconRef denv tc) prec prefix args
+
+        | TType_app (tc, args, nullness) ->
+            let prefix = usePrefix denv tc
+            let part1 = layoutTypeAppWithInfoAndPrec denv env (layoutTyconRef denv tc) prec prefix args
+            let part2 = layoutNullness denv part1 nullness
+            part2
 
         // Layout a tuple type 
         | TType_anon (anonInfo, tys) ->
@@ -935,17 +943,19 @@ module PrintTypes =
             | [h] -> layoutTyparRefWithInfo denv env h ^^ rightL (tagPunctuation ".") --- tauL
             | h :: t -> spaceListL (List.map (layoutTyparRefWithInfo denv env) (h :: t)) ^^ rightL (tagPunctuation ".") --- tauL
 
-        | TType_fun _ ->
+        | TType_fun (_, _, nullness) ->
             let argTys, retTy = stripFunTy g ty
             let retTyL = layoutTypeWithInfoAndPrec denv env 5 retTy
             let argTysL = argTys |> List.map (layoutTypeWithInfoAndPrec denv env 4)
             let funcTyL = curriedLayoutsL "->" argTysL retTyL
-            bracketIfL (prec <= 4) funcTyL
+            let part1 = bracketIfL (prec <= 4) funcTyL
+            let part2 = layoutNullness denv part1 nullness
+            part2
 
         // Layout a type variable . 
         | TType_var (r, nullness) ->
             let part1 = layoutTyparRefWithInfo denv env r
-            let part2 = layoutNullness part1 nullness
+            let part2 = layoutNullness denv part1 nullness
             part2
 
         | TType_measure unt -> layoutMeasure denv unt
@@ -2650,7 +2660,7 @@ let minimalStringsOfTwoTypes denv ty1 ty2 =
 
     // try denv + no type annotations 
     let attempt1 = 
-        let denv = { denv with showInferenceTyparAnnotations=false; showStaticallyResolvedTyparAnnotations=false }
+        let denv = { denv with showInferenceTyparAnnotations=false; showStaticallyResolvedTyparAnnotations=false; showNullnessAnnotations=false }
         let min1 = stringOfTy denv ty1
         let min2 = stringOfTy denv ty2
         if min1 <> min2 then Some (min1, min2, "") else None
@@ -2661,7 +2671,7 @@ let minimalStringsOfTwoTypes denv ty1 ty2 =
 
     // try denv + no type annotations + show full paths
     let attempt2 = 
-        let denv = { denv with showInferenceTyparAnnotations=false; showStaticallyResolvedTyparAnnotations=false }.SetOpenPaths []
+        let denv = { denv with showInferenceTyparAnnotations=false; showStaticallyResolvedTyparAnnotations=false; showNullnessAnnotations=false }.SetOpenPaths []
         let min1 = stringOfTy denv ty1
         let min2 = stringOfTy denv ty2
         if min1 <> min2 then Some (min1, min2, "") else None
@@ -2670,6 +2680,7 @@ let minimalStringsOfTwoTypes denv ty1 ty2 =
     | Some res -> res
     | None -> 
 
+    // try denv
     let attempt3 = 
         let min1 = stringOfTy denv ty1
         let min2 = stringOfTy denv ty2
@@ -2702,13 +2713,13 @@ let minimalStringsOfTwoTypes denv ty1 ty2 =
     
 // Note: Always show imperative annotations when comparing value signatures 
 let minimalStringsOfTwoValues denv infoReader vref1 vref2 = 
-    let denvMin = { denv with showInferenceTyparAnnotations=true; showStaticallyResolvedTyparAnnotations=false }
+    let denvMin = { denv with showInferenceTyparAnnotations=true; showStaticallyResolvedTyparAnnotations=false; showNullnessAnnotations=false }
     let min1 = buildString (fun buf -> outputQualifiedValOrMember denvMin infoReader buf vref1)
     let min2 = buildString (fun buf -> outputQualifiedValOrMember denvMin infoReader buf vref2) 
     if min1 <> min2 then 
         (min1, min2) 
     else
-        let denvMax = { denv with showInferenceTyparAnnotations=true; showStaticallyResolvedTyparAnnotations=true }
+        let denvMax = { denv with showInferenceTyparAnnotations=true; showStaticallyResolvedTyparAnnotations=true; showNullnessAnnotations=false }
         let max1 = buildString (fun buf -> outputQualifiedValOrMember denvMax infoReader buf vref1)
         let max2 = buildString (fun buf -> outputQualifiedValOrMember denvMax infoReader buf vref2) 
         max1, max2
diff --git a/src/Compiler/Checking/PostInferenceChecks.fs b/src/Compiler/Checking/PostInferenceChecks.fs
index cf855cd1ea7..cf18598d158 100644
--- a/src/Compiler/Checking/PostInferenceChecks.fs
+++ b/src/Compiler/Checking/PostInferenceChecks.fs
@@ -2533,26 +2533,17 @@ let CheckEntityDefn cenv env (tycon: Entity) =
         
         // Check fields. We check these late because we have to have first checked that the structs are
         // free of cycles
-        if g.langFeatureNullness then 
+        if g.langFeatureNullness && g.checkNullness then 
             for f in tycon.AllInstanceFieldsAsList do
                 let m = f.Range
                 // Check if it's marked unsafe 
                 let zeroInitUnsafe = TryFindFSharpBoolAttribute g g.attrib_DefaultValueAttribute f.FieldAttribs
                 if zeroInitUnsafe = Some true then
                     let ty = f.FormalType
-                    if not (TypeHasDefaultValueNew g m ty) && not (TypeHasDefaultValue g m ty) then 
-                        if tycon.IsStructOrEnumTycon then 
-                            // Under F# 4.5 we gave a hard error for this case so we can give it now
-                            errorR(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValue(), m))
-                        else
-                            if g.checkNullness then
-                                // Under F# 5.0 rules with checkNullness we can now give a warning for this case 
-                                warning(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValue(), m))
-
-                    elif g.checkNullness && not (TypeHasDefaultValueNew g m ty) then 
-                        // Under F# 5.0 rules with checkNullness we can now give a warning for this case 
-                        warning(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValueNulls(), m))
-        // These are the F# 4.5 rules, mistakenly only applied to structs
+                    if not (TypeHasDefaultValueNew g m ty) then 
+                        errorR(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValue(), m))
+
+        // These are the old rules (not g.langFeatureNullness or not g.checkNullness), mistakenly only applied to structs
         elif tycon.IsStructOrEnumTycon then 
             for f in tycon.AllInstanceFieldsAsList do
                 let m = f.Range
diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs
index d3e03d95735..038ef04488c 100644
--- a/src/Compiler/Driver/CompilerDiagnostics.fs
+++ b/src/Compiler/Driver/CompilerDiagnostics.fs
@@ -177,7 +177,7 @@ type Exception with
         | ConstraintSolverNullnessWarningEquivWithTypes (_, _, _, _, _, m, _)
         | ConstraintSolverNullnessWarningWithTypes (_, _, _, _, _, m, _)
         | ConstraintSolverNullnessWarningWithType (_, _, _, m, _)
-        | ConstraintSolverNonNullnessWarningWithType (_, _, _, m, _)
+        | ConstraintSolverNullnessWarning (_, m, _)
         | ConstraintSolverTypesNotInEqualityRelation (_, _, _, m, _, _)
         | ConstraintSolverError (_, m, _)
         | ConstraintSolverTypesNotInSubsumptionRelation (_, _, _, m, _)
@@ -344,9 +344,9 @@ type Exception with
         | ErrorsFromAddingSubsumptionConstraint (_, _, _, _, _, ContextInfo.DowncastUsedInsteadOfUpcast _, _) ->
             fst (FSComp.SR.considerUpcast ("", ""))
         | ConstraintSolverNullnessWarningEquivWithTypes _ -> 3261
-        | ConstraintSolverNullnessWarningWithTypes _ -> 3262
-        | ConstraintSolverNullnessWarningWithType _ -> 3263
-        | ConstraintSolverNonNullnessWarningWithType _ -> 3264
+        | ConstraintSolverNullnessWarningWithTypes _ -> 3261
+        | ConstraintSolverNullnessWarningWithType _ -> 3261
+        | ConstraintSolverNullnessWarning _ -> 3261
         | _ -> 193
 
 type PhasedDiagnostic with
@@ -450,10 +450,10 @@ module OldStyleMessages =
     let ConstraintSolverTupleDiffLengthsE () = Message("ConstraintSolverTupleDiffLengths", "%d%d")
     let ConstraintSolverInfiniteTypesE () = Message("ConstraintSolverInfiniteTypes", "%s%s")
     let ConstraintSolverMissingConstraintE () = Message("ConstraintSolverMissingConstraint", "%s")
-    let ConstraintSolverNullnessWarningEquivWithTypesE () = Message("ConstraintSolverNullnessWarningEquivWithTypes", "%s%s%s%s")
-    let ConstraintSolverNullnessWarningWithTypesE () = Message("ConstraintSolverNullnessWarningWithTypes", "%s%s%s%s")
+    let ConstraintSolverNullnessWarningEquivWithTypesE () = Message("ConstraintSolverNullnessWarningEquivWithTypes", "%s%s")
+    let ConstraintSolverNullnessWarningWithTypesE () = Message("ConstraintSolverNullnessWarningWithTypes", "%s%s")
     let ConstraintSolverNullnessWarningWithTypeE () = Message("ConstraintSolverNullnessWarningWithType", "%s")
-    let ConstraintSolverNonNullnessWarningWithTypeE () = Message("ConstraintSolverNonNullnessWarningWithType", "%s")
+    let ConstraintSolverNullnessWarningE () = Message("ConstraintSolverNullnessWarning", "%s")
     let ConstraintSolverTypesNotInEqualityRelation1E () = Message("ConstraintSolverTypesNotInEqualityRelation1", "%s%s")
     let ConstraintSolverTypesNotInEqualityRelation2E () = Message("ConstraintSolverTypesNotInEqualityRelation2", "%s%s")
     let ConstraintSolverTypesNotInSubsumptionRelationE () = Message("ConstraintSolverTypesNotInSubsumptionRelation", "%s%s%s")
@@ -676,21 +676,21 @@ type Exception with
             if m.StartLine <> m2.StartLine then
                 os.AppendString(SeeAlsoE().Format(stringOfRange m))
 
-        | ConstraintSolverNullnessWarningEquivWithTypes (denv, ty1, ty2, nullness1, nullness2, m, m2) ->
+        | ConstraintSolverNullnessWarningEquivWithTypes (denv, ty1, ty2, _nullness1, _nullness2, m, m2) ->
 
             let t1, t2, _cxs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2
 
-            os.Append(ConstraintSolverNullnessWarningEquivWithTypesE().Format t1 t2 (nullness1.ToString()) (nullness2.ToString()))
+            os.Append(ConstraintSolverNullnessWarningEquivWithTypesE().Format t1 t2)
             |> ignore
 
             if m.StartLine <> m2.StartLine then
                 os.Append(SeeAlsoE().Format(stringOfRange m)) |> ignore
 
-        | ConstraintSolverNullnessWarningWithTypes (denv, ty1, ty2, nullness1, nullness2, m, m2) ->
+        | ConstraintSolverNullnessWarningWithTypes (denv, ty1, ty2, _nullness1, _nullness2, m, m2) ->
 
             let t1, t2, _cxs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2
 
-            os.Append(ConstraintSolverNullnessWarningWithTypesE().Format t1 t2 (nullness1.ToString()) (nullness2.ToString()))
+            os.Append(ConstraintSolverNullnessWarningWithTypesE().Format t1 t2)
             |> ignore
 
             if m.StartLine <> m2.StartLine then
@@ -704,13 +704,11 @@ type Exception with
             if m.StartLine <> m2.StartLine then
                 os.Append(SeeAlsoE().Format(stringOfRange m)) |> ignore
 
-        | ConstraintSolverNonNullnessWarningWithType (denv, ty, _, m, m2) ->
-
-            let t = NicePrint.minimalStringOfType denv ty
-            os.Append(ConstraintSolverNonNullnessWarningWithTypeE().Format(t)) |> ignore
+        | ConstraintSolverNullnessWarning (msg, m, m2) ->
+            os.Append(ConstraintSolverNullnessWarningE().Format(msg)) |> ignore
 
             if m.StartLine <> m2.StartLine then
-                os.Append(SeeAlsoE().Format(stringOfRange m)) |> ignore
+                os.AppendString(SeeAlsoE().Format(stringOfRange m2))
 
         | ConstraintSolverMissingConstraint (denv, tpr, tpc, m, m2) ->
             os.AppendString(
diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt
index fce80a8d230..6c136004759 100644
--- a/src/Compiler/FSComp.txt
+++ b/src/Compiler/FSComp.txt
@@ -1516,17 +1516,15 @@ notAFunctionButMaybeDeclaration,"This value is not a function and cannot be appl
 3252,tcIllegalByrefsInOpenTypeDeclaration,"Byref types are not allowed in an open type declaration."
 3260,tcTypeDoesNotHaveAnyNull,"The type '%s' does not support a nullness qualitification."
 #3261 reserved for ConstraintSolverNullnessWarningEquivWithTypes
-#3262 reserved for ConstraintSolverNullnessWarningWithTypes
-#3263 reserved for ConstraintSolverNullnessWarningWithType
-#3264 reserved for ConstraintSolverNonNullnessWarningWithType
-3266,tcDefaultStructConstructorCallNulls,"Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable."
-3267,chkValueWithDefaultValueMustHaveDefaultValueNulls,"Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable."
+#3261 reserved for ConstraintSolverNullnessWarningWithTypes
+#3261 reserved for ConstraintSolverNullnessWarningWithType
+#3261 reserved for ConstraintSolverNullnessWarning
 3268,csNullNotNullConstraintInconsistent,"The constraints 'null' and 'not null' are inconsistent"
 3269,csStructNullConstraintInconsistent,"The constraints 'struct' and 'null' are inconsistent"
 3270,csDelegateComparisonConstraintInconsistent,"The constraints 'delegate' and 'comparison' are inconsistent"
 3271,tcNullnessCheckingNotEnabled,"The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored."
-csTypeHasNullAsTrueValue,"The type '%s' has 'null' as a true representation value but a constraint does not permit this"
-csTypeHasNullAsExtraValue,"The type '%s' has 'null' as an extra value but a constraint does not permit this"
+csTypeHasNullAsTrueValue,"The type '%s' uses 'null' as a representation value but a non-null type is expected"
+csTypeHasNullAsExtraValue,"The type '%s' supports 'null' but a non-null type is expected"
 3300,chkInvalidFunctionParameterType,"The parameter '%s' has an invalid type '%s'. This is not permitted by the rules of Common IL."
 3301,chkInvalidFunctionReturnType,"The function or method has an invalid return type '%s'. This is not permitted by the rules of Common IL."
 3302,packageManagementRequiresVFive,"The 'package management' feature requires language version 5.0 or above"
diff --git a/src/Compiler/FSStrings.resx b/src/Compiler/FSStrings.resx
index 417b7b77fe0..83a8b332faf 100644
--- a/src/Compiler/FSStrings.resx
+++ b/src/Compiler/FSStrings.resx
@@ -130,16 +130,16 @@
     A type parameter is missing a constraint '{0}'
   
   
-    Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+    Nullness warning: A non-null type is expected. The types '{0}' and '{1}' do not have equivalent nullability.
   
   
-    Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+    Nullness warning: A non-null type is expected. The types '{0}' and '{1}' do not have compatible nullability.
   
   
-    Nullness warning: The type '{0}' does not support nullness.
+    Nullness warning: The type '{0}' is non-null, but a type supporting 'null' is expected.
   
-  
-    Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+  
+    Nullness warning: {0}.
   
   
     The unit of measure '{0}' does not match the unit of measure '{1}'
diff --git a/src/Compiler/Symbols/SymbolHelpers.fs b/src/Compiler/Symbols/SymbolHelpers.fs
index 67161c99f0f..11a9623bff1 100644
--- a/src/Compiler/Symbols/SymbolHelpers.fs
+++ b/src/Compiler/Symbols/SymbolHelpers.fs
@@ -543,6 +543,7 @@ module internal SymbolHelpers =
     let SimplerDisplayEnv denv = 
         { denv with shortConstraints=true
                     showStaticallyResolvedTyparAnnotations=false
+                    showNullnessAnnotations=false
                     abbreviateAdditionalConstraints=false
                     suppressNestedTypes=true
                     maxMembers=Some EnvMisc2.maxMembers }
diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs
index 755e2e725ab..2b4e5af995c 100644
--- a/src/Compiler/TypedTree/TypedTreeOps.fs
+++ b/src/Compiler/TypedTree/TypedTreeOps.fs
@@ -3078,6 +3078,7 @@ type DisplayEnv =
       showAttributes: bool
       showOverrides: bool
       showStaticallyResolvedTyparAnnotations: bool
+      showNullnessAnnotations: bool
       abbreviateAdditionalConstraints: bool
       showTyparDefaultConstraints: bool
       showDocumentation: bool
@@ -3112,6 +3113,7 @@ type DisplayEnv =
         showAttributes = false
         showOverrides = true
         showStaticallyResolvedTyparAnnotations = true
+        showNullnessAnnotations = true
         showDocumentation = false
         abbreviateAdditionalConstraints = false
         showTyparDefaultConstraints = false
@@ -8895,19 +8897,6 @@ let TypeNullNever g ty =
     isByrefTy g underlyingTy ||
     isNonNullableStructTyparTy g ty
 
-let TyconRefNullIsExtraValueAux isNew g m (tcref: TyconRef) = 
-    not tcref.IsStructOrEnumTycon &&
-    not (isByrefLikeTyconRef g m tcref) && 
-    (if tcref.IsILTycon then 
-        // Putting AllowNullLiteralAttribute(false) on an IL or provided type means 'null' can't be used with that type
-        (not isNew && TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref <> Some false)
-     else 
-// Putting AllowNullLiteralAttribute(true) on an F# type means it always admits null even in the new model
-        (TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref = Some true))
-
-let TyconRefNullIsExtraValue g m tcref = TyconRefNullIsExtraValueAux false g m tcref
-let TyconRefNullIsExtraValueNew g m tcref = TyconRefNullIsExtraValueAux true g m tcref
-
 /// The F# 4.5 logic about whether a type admits the use of 'null' as a value.
 let TypeNullIsExtraValue g m ty = 
     if isILReferenceTy g ty || isDelegateTy g ty then
@@ -8936,6 +8925,8 @@ let TypeNullIsExtraValue g m ty =
 /// The new logic about whether a type admits the use of 'null' as a value.
 let TypeNullIsExtraValueNew g m ty = 
     let sty = stripTyparEqns ty
+    isObjTy g sty
+    ||
     (match tryTcrefOfAppTy g sty with 
      | ValueSome tcref -> 
         not tcref.IsStructOrEnumTycon &&
@@ -8965,10 +8956,6 @@ let TypeNullNotLiked g m ty =
     && not (TypeNullIsTrueValue g ty) 
     && not (TypeNullNever g ty) 
 
-// The non-inferring counter-part to SolveTypeUseSupportsNull
-let TypeSatisfiesNullConstraint g m ty = 
-    TypeNullIsExtraValue g m ty  
-
 let rec TypeHasDefaultValueAux isNew g m ty = 
     let ty = stripTyEqnsAndMeasureEqns g ty
     (if isNew then TypeNullIsExtraValueNew g m ty else TypeNullIsExtraValue g m ty)
@@ -9001,7 +8988,7 @@ let rec TypeHasDefaultValueAux isNew g m ty =
       (isNonNullableStructTyparTy g ty &&
         (destTyparTy g ty).Constraints |> List.exists (function TyparConstraint.RequiresDefaultConstructor _ -> true | _ -> false))
 
-let TypeHasDefaultValue g m ty = TypeHasDefaultValueAux false g m ty  
+let TypeHasDefaultValue (g: TcGlobals) m ty = TypeHasDefaultValueAux false g m ty  
 
 let TypeHasDefaultValueNew g m ty = TypeHasDefaultValueAux true g m ty  
 
diff --git a/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi
index 1dee86e329b..514c778a4b6 100755
--- a/src/Compiler/TypedTree/TypedTreeOps.fsi
+++ b/src/Compiler/TypedTree/TypedTreeOps.fsi
@@ -1061,6 +1061,7 @@ type DisplayEnv =
         showAttributes: bool
         showOverrides: bool
         showStaticallyResolvedTyparAnnotations: bool
+        showNullnessAnnotations: bool
         abbreviateAdditionalConstraints: bool
         showTyparDefaultConstraints: bool
         /// If set, signatures will be rendered with XML documentation comments for members if they exist
@@ -1742,20 +1743,16 @@ val CompileAsEvent: TcGlobals -> Attribs -> bool
 
 val TypeNullIsTrueValue: TcGlobals -> TType -> bool
 
-val TypeNullIsExtraValueNew: TcGlobals -> range -> TType -> bool
-
 val TypeNullIsExtraValue: TcGlobals -> range -> TType -> bool
 
-val TyconRefNullIsExtraValue: TcGlobals -> range -> TyconRef -> bool
-
-val TyconRefNullIsExtraValueNew: TcGlobals -> range -> TyconRef -> bool
+val TypeNullIsExtraValueNew: TcGlobals -> range -> TType -> bool
 
 val TypeNullNever: TcGlobals -> TType -> bool
 
-val TypeHasDefaultValueNew: TcGlobals -> range -> TType -> bool
-
 val TypeHasDefaultValue: TcGlobals -> range -> TType -> bool
 
+val TypeHasDefaultValueNew: TcGlobals -> range -> TType -> bool
+
 val isAbstractTycon: Tycon -> bool
 
 val isUnionCaseRefDefinitelyMutable: UnionCaseRef -> bool
diff --git a/tests/adhoc/nullness/enabled/negative.fs b/tests/adhoc/nullness/enabled/negative.fs
new file mode 100644
index 00000000000..6982a8baf5e
--- /dev/null
+++ b/tests/adhoc/nullness/enabled/negative.fs
@@ -0,0 +1,5 @@
+open System
+
+module Basics2 = 
+    let f6 () : 'T __withnull when 'T : not struct and 'T : null = null // Expected to give an error about inconistent constraints
+
diff --git a/tests/adhoc/nullness/enabled/positive.fs b/tests/adhoc/nullness/enabled/positive.fs
new file mode 100644
index 00000000000..44b43ea9ea9
--- /dev/null
+++ b/tests/adhoc/nullness/enabled/positive.fs
@@ -0,0 +1,280 @@
+open System
+
+module Basics =     
+    let x2 : String __withnull = null // expect no warning in any configuration
+    let x3 : String __withnull = "a"  // expect no warning in any configuration
+
+module NotNullConstraint =
+    let f3 (x: 'T when 'T : __notnull) = 1
+    let v1 = f3 1 
+    let v2 = f3 "a"
+    let v3 = f3 (null: obj) // Expect no warning in any configuration - warnings about 'obj' and nulls are suppressed 
+    let v4 = f3 (null: String __withnull) // Expect to give a warning
+    let v5 = f3 (Some 1) // Expect to give a warning
+
+    let w1 = 1 |> f3
+    let w2 = "a" |> f3
+    let w3 = (null: obj) |> f3 // Expect no warning in any configuration - warnings about 'obj' and nulls are suppressed 
+    let w4 = (null: String __withnull) |> f3 // Expect to give a warning
+    let w5 = (Some 1) |> f3 // Expect to give a warning
+
+module MemberBasics = 
+    type C() = 
+        member x.P = 1
+        member x.M() = 2
+
+    let c : C __withnull = C()
+    let v1 = c.P  // Expected to give a warning
+    let v2 = c.M()  // Expected to give a warning
+    let f1 = c.M  // Expected to give a warning
+
+
+module Basics2 = 
+    let f1 () = null
+
+    let f2 () : String __withnull = null
+
+    let f3 () : 'T __withnull = null
+
+    let f4 () : 'T __withnull when 'T : not struct = null
+
+    let f5 () : 'T when 'T : not struct and 'T : null = null
+
+    let f8 () : String = null // Expected to give a Nullness warning
+
+
+type C(s: String) = 
+    member __.Value = s
+
+
+// This give a warning since 'T is not known to be reference type non-null
+let f<'T> (x: 'T __withnull, y: 'T __withnull) = ()
+
+module Extractions0c =
+
+    let x = null
+    let f<'T when 'T : __notnull> (x: 'T __withnull, y: 'T __withnull) = ()
+    let s : String = ""
+    let result = f (x, s)   // expect no warning in any configuration
+
+module Extractions0e =
+
+    let x = null
+    let f<'T when 'T : __notnull> (x: 'T __withnull, y: 'T __withnull) = ()
+    let result = f (x, "") // expect no warning in any configuration
+
+module Extractions1 =
+
+    let mutable x : _ __withnull = null
+    x <- ""  // expect no warning
+
+//let f<'T when 'T : not struct> (x: 'T __withnull) = 1
+module InteropBasics =
+    let s0 = String.Concat("a","b")
+    let s1 : String = String.Concat("a","c")
+    let test1()  = String.Concat("a","d")
+    let test2(s1:String, s2: String)  = String.Concat(s1,s2)
+    let test3()  = String( [| 'a' |] )
+    let test4()  = System.AppDomain.CurrentDomain
+    let test5 : System.AppDomain  = System.AppDomain.CurrentDomain
+
+type KonsoleWithNulls = 
+    static member WriteLine(s: String __withnull) = Console.WriteLine(s)
+    static member WriteLine(fmt: String __withnull, arg1: String __withnull) = Console.WriteLine(fmt, arg1)
+    static member WriteLine(fmt: String __withnull, [] args: obj __withnull[] __withnull) = Console.WriteLine(fmt, args)
+    static member WriteLineC(s: C __withnull) = Console.WriteLine(s.Value)
+    static member WriteLineC(fmt: C __withnull, arg1: C __withnull) = Console.WriteLine(fmt.Value, arg1.Value)
+
+module KonsoleWithNullsModule = 
+    let WriteLine(s: String __withnull) = Console.WriteLine(s)
+    let WriteLine2(fmt: String __withnull, arg1: String __withnull) = Console.WriteLine(fmt, arg1)
+    let WriteLineC(s: C __withnull) = Console.WriteLine(s.Value)
+    let WriteLineC2(fmt: C __withnull, arg1: C __withnull) = Console.WriteLine(fmt.Value, arg1.Value)
+
+module KonsoleWithNullsModule2 = 
+    let WriteLine x = KonsoleWithNullsModule.WriteLine x
+    let WriteLine2 (fmt, arg1) = KonsoleWithNullsModule.WriteLine2(fmt, arg1)
+    let WriteLineC(s) = KonsoleWithNullsModule.WriteLineC(s)
+    let WriteLineC2(fmt, arg1) = KonsoleWithNullsModule.WriteLineC2(fmt, arg1)
+
+type KonsoleNoNulls = 
+    static member WriteLine(s: String) = Console.WriteLine(s)
+    static member WriteLine(fmt: String, arg1: String __withnull) = Console.WriteLine(fmt, arg1)
+    static member WriteLine(fmt: String, [] args: obj[]) = Console.WriteLine(fmt, args)
+    static member WriteLineC(s: C) = Console.WriteLine(s.Value)
+    static member WriteLineC(fmt: C, arg1: C) = Console.WriteLine(fmt.Value, arg1.Value)
+
+module KonsoleNoNullsModule = 
+    let WriteLine(s: String) = Console.WriteLine(s)
+    let WriteLine2(fmt: String, arg1: String) = Console.WriteLine(fmt, arg1)
+    let WriteLineC(s: C) = Console.WriteLine(s.Value)
+    let WriteLineC2(fmt: C, arg1: C) = Console.WriteLine(fmt.Value, arg1.Value)
+
+module KonsoleNoNullsModule2 = 
+    let WriteLine x = KonsoleNoNullsModule.WriteLine x
+    let WriteLine2 (fmt, arg1) = KonsoleNoNullsModule.WriteLine2(fmt, arg1)
+    let WriteLineC(s) = KonsoleNoNullsModule.WriteLineC(s)
+    let WriteLineC2(fmt, arg1) = KonsoleNoNullsModule.WriteLineC2(fmt, arg1)
+
+System.Console.WriteLine("a")
+System.Console.WriteLine("a", (null: obj[])) // Expected to give a Nullness warning
+
+KonsoleWithNulls.WriteLine("Hello world")
+KonsoleWithNulls.WriteLine(null) // WRONG: gives an incorrect Nullness warning for String __withnull and String __withnull
+KonsoleWithNulls.WriteLine("Hello","world")
+KonsoleWithNulls.WriteLine("Hello","world","there") // // WRONG: gives an incorrect Nullness warning for String __withnull and String __withnull
+
+KonsoleNoNulls.WriteLine("Hello world")
+try 
+   KonsoleNoNulls.WriteLine(null)  // Expected to give a Nullness warning
+with :? System.ArgumentNullException -> ()
+KonsoleNoNulls.WriteLine("Hello","world")
+//KonsoleNoNulls.WriteLine("Hello",null) // CHECK ME 
+try 
+    KonsoleNoNulls.WriteLine(null, "World")   // Expected to give a Nullness warning
+with :? System.ArgumentNullException -> ()
+
+KonsoleWithNullsModule.WriteLine("Hello world")
+try 
+    KonsoleWithNullsModule.WriteLine(null) 
+with :? System.ArgumentNullException -> ()
+KonsoleWithNullsModule.WriteLine2("Hello","world") 
+KonsoleWithNullsModule.WriteLine2("Hello",null)
+try
+    KonsoleWithNullsModule.WriteLine2(null,"world")
+with :? System.ArgumentNullException -> ()
+
+KonsoleWithNullsModule2.WriteLine("Hello world")
+try 
+    KonsoleWithNullsModule2.WriteLine(null) 
+with :? System.ArgumentNullException -> ()
+KonsoleWithNullsModule2.WriteLine2("Hello","world")
+KonsoleWithNullsModule2.WriteLine2("Hello",null)
+try 
+    KonsoleWithNullsModule2.WriteLine2(null,"world")
+with :? System.ArgumentNullException -> ()
+
+KonsoleNoNullsModule.WriteLine("Hello world")
+try 
+    KonsoleNoNullsModule.WriteLine(null)  // Expected to give a Nullness warning
+with :? System.ArgumentNullException -> ()
+KonsoleNoNullsModule.WriteLine2("Hello","world")
+KonsoleNoNullsModule.WriteLine2("Hello",null) // Expected to give a Nullness warning
+try 
+    KonsoleNoNullsModule.WriteLine2(null,"world") // Expected to give a Nullness warning
+with :? System.ArgumentNullException -> ()
+
+//-------------------------------------
+
+// Param array cases
+
+KonsoleNoNulls.WriteLine("Hello","world","there")
+KonsoleWithNulls.WriteLine("Hello","world",null)  // Expected to give a Nullness warning 
+KonsoleNoNulls.WriteLine("Hello","world",null)  // Expected to give a Nullness warning
+System.Console.WriteLine("a", (null: obj[] __withnull)) 
+System.Console.WriteLine("a", (null: obj __withnull[] __withnull))
+
+//-------
+// random stuff
+
+let f0 line = 
+    let add (s:String) = ()
+    match line with 
+    | null | "" -> ()
+    | _ -> add line // Exected to give a nullness warning
+
+module NullConstraintTests =
+    type C<'T when 'T : null>() = class end
+
+    let f1 (y : C< (int * int) >) = y // This gave an error in previous F# and we expect it to continue to give an error
+
+    // This gave an error in previous F#.
+    let f2 (y : C) = y
+
+    let f3 (y : C) = y // Expect a Nullness warning
+
+    let f4 (y : C) = y // No warning expected 
+
+    let f5 (y : C __withnull>) = y // No warning expected
+
+    let f6 (y : C __withnull>) = y // No warning expected, lexing/parsing should succeed 
+
+    let f7 (y : C> __withnull) = y // No warning expected, lexing/parsing should succeed
+
+
+module DefaultValueTests =
+
+
+    module StructExamples = 
+        []
+        type C1 =
+            []
+            val mutable Whoops : String // expect a warning
+
+        []
+        type C2 =
+            []
+            val mutable Whoops : String // expect no warning
+
+        []
+        type C3 =
+            []
+            val mutable Whoops : String __withnull // expect no warning
+
+        []
+        type C4a =
+            []
+            val mutable Whoops : int FSharp.Collections.List // expect a hard error like in previous F#
+
+        []
+        type C4b =
+            []
+            val mutable Whoops : int FSharp.Collections.List __withnull // expect no warning
+
+        []
+        type C5 =
+            []
+            val mutable Whoops : int * int // expect an error like previous F#
+
+        []
+        type C6 =
+            []
+            val mutable Whoops : int -> int // expect an error like previous F#
+
+        []
+        type C7 =
+            []
+            val mutable Whoops : (int -> int) __withnull // expect no warning
+
+    module ClassExamples = 
+        type C1 =
+            []
+            val mutable Whoops : String // expect a warning
+
+        type C2 =
+            []
+            val mutable Whoops : String // expect no warning
+
+        type C3 =
+            []
+            val mutable Whoops : String __withnull // expect no warning
+
+        type C4a =
+            []
+            val mutable Whoops : int FSharp.Collections.List // ** expect a warning
+
+        type C4b =
+            []
+            val mutable Whoops : int FSharp.Collections.List __withnull // expect no warning
+
+        type C5 =
+            []
+            val mutable Whoops : int * int // expect an error like previous F#
+
+        type C6 =
+            []
+            val mutable Whoops : int -> int // expect an error like previous F#
+
+        type C7 =
+            []
+            val mutable Whoops : (int -> int) __withnull // expect no warning
diff --git a/tests/adhoc/nullness/enabled/positive.next.bsl b/tests/adhoc/nullness/enabled/positive.next.bsl
new file mode 100644
index 00000000000..8aa67c5962e
--- /dev/null
+++ b/tests/adhoc/nullness/enabled/positive.next.bsl
@@ -0,0 +1,16 @@
+
+tests\adhoc\nullness\enabled\positive.fs(8,24): warning FS3271: The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+
+tests\adhoc\nullness\enabled\positive.fs(56,19): warning FS3271: The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+
+tests\adhoc\nullness\enabled\positive.fs(63,19): warning FS3271: The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+
+tests\adhoc\nullness\enabled\positive.fs(208,17): error FS0001: The type '(int * int)' does not have 'null' as a proper value
+
+tests\adhoc\nullness\enabled\positive.fs(214,17): error FS0001: The type 'int list' does not have 'null' as a proper value
+
+tests\adhoc\nullness\enabled\positive.fs(220,17): error FS0001: The type 'int list' does not have 'null' as a proper value
+
+tests\adhoc\nullness\enabled\positive.fs(222,17): error FS0001: The type 'String list' does not have 'null' as a proper value
+
+tests\adhoc\nullness\enabled\positive.fs(224,17): error FS0001: The type 'String list' does not have 'null' as a proper value
diff --git a/tests/adhoc/nullness/enabled/positive.next.enabled.bsl b/tests/adhoc/nullness/enabled/positive.next.enabled.bsl
new file mode 100644
index 00000000000..ac6614cea16
--- /dev/null
+++ b/tests/adhoc/nullness/enabled/positive.next.enabled.bsl
@@ -0,0 +1,18 @@
+
+tests\adhoc\nullness\enabled\positive.fs(13,18): warning FS3261: Nullness warning: The type ''a option' uses 'null' as a representation value but a non-null type is expected.
+
+tests\adhoc\nullness\enabled\positive.fs(19,26): warning FS3261: Nullness warning: The type 'int option' uses 'null' as a representation value but a non-null type is expected.
+
+tests\adhoc\nullness\enabled\positive.fs(51,15): error FS0043: A type parameter is missing a constraint 'when 'T: __notnull'
+
+tests\adhoc\nullness\enabled\positive.fs(51,33): error FS0043: A type parameter is missing a constraint 'when 'T: __notnull'
+
+tests\adhoc\nullness\enabled\positive.fs(208,17): error FS0001: The type '(int * int)' does not have 'null' as a proper value
+
+tests\adhoc\nullness\enabled\positive.fs(214,17): error FS0001: The type 'int list' does not have 'null' as a proper value
+
+tests\adhoc\nullness\enabled\positive.fs(220,17): error FS0001: The type 'int list __withnull' does not have 'null' as a proper value
+
+tests\adhoc\nullness\enabled\positive.fs(222,17): error FS0001: The type 'String list __withnull' does not have 'null' as a proper value
+
+tests\adhoc\nullness\enabled\positive.fs(224,17): error FS0001: The type 'String list' does not have 'null' as a proper value
diff --git a/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl b/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl
new file mode 100644
index 00000000000..eb4c0a63735
--- /dev/null
+++ b/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl
@@ -0,0 +1,70 @@
+
+tests\adhoc\nullness\enabled\positive.fs(12,18): warning FS3261: Nullness warning: The type 'String __withnull' supports 'null' but a non-null type is expected.
+
+tests\adhoc\nullness\enabled\positive.fs(13,18): warning FS3261: Nullness warning: The type ''a option' uses 'null' as a representation value but a non-null type is expected.
+
+tests\adhoc\nullness\enabled\positive.fs(18,43): warning FS3261: Nullness warning: The type 'String __withnull' supports 'null' but a non-null type is expected.
+
+tests\adhoc\nullness\enabled\positive.fs(19,26): warning FS3261: Nullness warning: The type 'int option' uses 'null' as a representation value but a non-null type is expected.
+
+tests\adhoc\nullness\enabled\positive.fs(27,14): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(27,14): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(28,14): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(28,14): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(29,14): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(29,14): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(43,26): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+
+tests\adhoc\nullness\enabled\positive.fs(51,15): error FS0043: A type parameter is missing a constraint 'when 'T: __notnull'
+
+tests\adhoc\nullness\enabled\positive.fs(51,33): error FS0043: A type parameter is missing a constraint 'when 'T: __notnull'
+
+tests\adhoc\nullness\enabled\positive.fs(88,67): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(88,67): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(89,89): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(89,89): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(89,100): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(89,100): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(94,57): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(94,57): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(95,80): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(95,80): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(95,91): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(95,91): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(123,32): warning FS3261: Nullness warning: The type 'obj array' is non-null, but a type supporting 'null' is expected.
+
+tests\adhoc\nullness\enabled\positive.fs(132,4): warning FS3261: Nullness warning: A non-null type is expected. The types 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' and 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(137,5): warning FS3261: Nullness warning: A non-null type is expected. The types 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' and 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' do not have compatible nullability.
+
+tests\adhoc\nullness\enabled\positive.fs(162,36): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+
+tests\adhoc\nullness\enabled\positive.fs(165,41): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+
+tests\adhoc\nullness\enabled\positive.fs(167,37): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+
+tests\adhoc\nullness\enabled\positive.fs(208,17): warning FS3261: Nullness warning: The type '(int * int)' is non-null, but a type supporting 'null' is expected.
+
+tests\adhoc\nullness\enabled\positive.fs(211,17): warning FS3261: Nullness warning: The type 'List' is non-null, but a type supporting 'null' is expected.
+
+tests\adhoc\nullness\enabled\positive.fs(213,17): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+
+tests\adhoc\nullness\enabled\positive.fs(221,17): warning FS3261: Nullness warning: The type 'List' is non-null, but a type supporting 'null' is expected.
diff --git a/tests/adhoc/nullness/existing/negative.fs b/tests/adhoc/nullness/existing/negative.fs
new file mode 100644
index 00000000000..1291546a2d9
--- /dev/null
+++ b/tests/adhoc/nullness/existing/negative.fs
@@ -0,0 +1,107 @@
+open System
+open System.Diagnostics
+open System.Runtime.CompilerServices
+
+module NullConstraintTests =
+    type C<'T when 'T : null>() = class end
+
+    let f1 (y : C< (int * int) >) = y // This gave an error in F# 4.5 and we expect it to continue to give an error
+
+    let f2 (y : C) = y // This gave an error in F# 4.5 and we expect it to continue to give an error
+
+module DefaultValueTests =
+
+    module StructExamples = 
+        []
+        type C4a =
+            []
+            val mutable Whoops : int list // This gave an error in F# 4.5 and we expect it to continue to give an error
+
+        []
+        type C5 =
+            []
+            val mutable Whoops : int * int // This gave an error in F# 4.5 and we expect it to continue to give an error
+
+        []
+        type C6 =
+            []
+            val mutable Whoops : int -> int // This gave an error in F# 4.5 and we expect it to continue to give an error
+
+    module ClassExamples = 
+
+        type C4a =
+            []
+            val mutable Whoops : int list // should have given an error in F# 4.5 but didn't
+
+        type C5 =
+            []
+            val mutable Whoops : int * int // should have given an error in F# 4.5 but didn't
+
+        type C6 =
+            []
+            val mutable Whoops : int -> int // should have given an error in F# 4.5 but didn't
+
+
+#if LIBRARY_SUPPORT
+module Library =     
+
+    let x5 = nonNull "" // Should not give a Nullness warning
+    check "ekjnceoiwe5" x5 ""
+    let x6 = nonNull "" // **Expected to give a Nullness warning, expected also to give a warning with nullness checking off
+    check "ekjnceoiwe6" x6 ""
+    let x7 = nonNull ""
+    check "ekjnceoiwe7" x7 ""
+    let _x7 : string = x7
+    let x8 = nonNull Array.empty
+    check "ekjnceoiwe8" x8 [| |]
+    let x9 = nonNull [| "" |]
+    check "ekjnceoiwe9" x9 [| "" |]
+    let x10 = nonNullV (Nullable(3))
+    check "ekjnceoiwe10" x10 3
+    let x11 = try nonNullV (Nullable()) with :? System.NullReferenceException -> 10
+    check "ekjnceoiwe11" x11 10
+    let x12 = nullV
+    check "ekjnceoiwe12" x12 (Nullable())
+    let x13 = nullV
+    check "ekjnceoiwe13" x13 (Nullable())
+    let x14 = withNullV 6L
+    check "ekjnceoiwe14" x14 (Nullable(6L))
+    let x15 : string __withnull = withNull x4
+    check "ekjnceoiwe15" x15 ""
+    let x15a : string __withnull = withNull ""
+    check "ekjnceoiwe15a" x15a ""
+    let x15b : string __withnull = withNull x4
+    check "ekjnceoiwe15b" x15b ""
+    let x15c : string __withnull = withNull x4 // **Expected to give a Nullness warning
+    check "ekjnceoiwe15c" x15c ""
+    let x16 : Nullable = withNullV 3
+    check "ekjnceoiwe16" x16 (Nullable(3))
+    
+    let y0 = isNull null // Should not give a Nullness warning (obj)
+    check "ekjnceoiwey0" y0 true
+    let y1 = isNull (null: obj __withnull) // Should not give a Nullness warning
+    check "ekjnceoiwey1" y1 true
+    let y1b = isNull (null: string __withnull) // Should not give a Nullness warning
+    check "ekjnceoiwey1b" y1b true
+    let y2 = isNull "" // **Expected to give a Nullness warning - type instantiation of a nullable type is non-nullable string
+    check "ekjnceoiwey2" y2 false
+    let y9 = isNull "" // **Expected to give a Nullness warning - type instantiation of a nullable type is non-nullable string
+    check "ekjnceoiwey9" y9 false
+    let y10 = isNull "" // Should not give a Nullness warning.
+    check "ekjnceoiwey10" y10 false
+    // Not yet allowed 
+    //let f7 () : 'T __withnull when 'T : struct = null
+    let f7b () : Nullable<'T> = nullV // BUG: Incorrectly gives a warning about System.ValueType with /test:AssumeNullOnImport
+
+    let f0b line = 
+        let add (s:string) = ()
+        match line with 
+        | null  -> ()
+        | _ -> add (nonNull line) // Exected to give a nullness warning
+
+    let add (s:string) = ()
+    let f0c line = 
+        add (nonNull "") // WRONG: should not give a nullness warning
+
+
+#endif
diff --git a/tests/adhoc/nullness/existing/negative.next.bsl b/tests/adhoc/nullness/existing/negative.next.bsl
new file mode 100644
index 00000000000..c1f4ac01b13
--- /dev/null
+++ b/tests/adhoc/nullness/existing/negative.next.bsl
@@ -0,0 +1,4 @@
+
+tests\adhoc\nullness\existing\negative.fs(8,17): error FS0001: The type '(int * int)' does not have 'null' as a proper value
+
+tests\adhoc\nullness\existing\negative.fs(10,17): error FS0001: The type 'int list' does not have 'null' as a proper value
diff --git a/tests/adhoc/nullness/existing/negative.next.enabled.bsl b/tests/adhoc/nullness/existing/negative.next.enabled.bsl
new file mode 100644
index 00000000000..c1f4ac01b13
--- /dev/null
+++ b/tests/adhoc/nullness/existing/negative.next.enabled.bsl
@@ -0,0 +1,4 @@
+
+tests\adhoc\nullness\existing\negative.fs(8,17): error FS0001: The type '(int * int)' does not have 'null' as a proper value
+
+tests\adhoc\nullness\existing\negative.fs(10,17): error FS0001: The type 'int list' does not have 'null' as a proper value
diff --git a/tests/adhoc/nullness/existing/negative.next.enabled.checknulls.bsl b/tests/adhoc/nullness/existing/negative.next.enabled.checknulls.bsl
new file mode 100644
index 00000000000..ea1aad9ff41
--- /dev/null
+++ b/tests/adhoc/nullness/existing/negative.next.enabled.checknulls.bsl
@@ -0,0 +1,14 @@
+
+tests\adhoc\nullness\existing\negative.fs(8,17): warning FS3261: Nullness warning: The type '(int * int)' is non-null, but a type supporting 'null' is expected.
+
+tests\adhoc\nullness\existing\negative.fs(18,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+
+tests\adhoc\nullness\existing\negative.fs(23,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+
+tests\adhoc\nullness\existing\negative.fs(28,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+
+tests\adhoc\nullness\existing\negative.fs(34,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+
+tests\adhoc\nullness\existing\negative.fs(38,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+
+tests\adhoc\nullness\existing\negative.fs(42,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
diff --git a/tests/adhoc/nullness/existing/negative.previous.bsl b/tests/adhoc/nullness/existing/negative.previous.bsl
new file mode 100644
index 00000000000..c1f4ac01b13
--- /dev/null
+++ b/tests/adhoc/nullness/existing/negative.previous.bsl
@@ -0,0 +1,4 @@
+
+tests\adhoc\nullness\existing\negative.fs(8,17): error FS0001: The type '(int * int)' does not have 'null' as a proper value
+
+tests\adhoc\nullness\existing\negative.fs(10,17): error FS0001: The type 'int list' does not have 'null' as a proper value
diff --git a/tests/adhoc/nullness/existing/positive.fs b/tests/adhoc/nullness/existing/positive.fs
new file mode 100644
index 00000000000..505034ad95b
--- /dev/null
+++ b/tests/adhoc/nullness/existing/positive.fs
@@ -0,0 +1,89 @@
+open System
+open System.Diagnostics
+open System.Runtime.CompilerServices
+
+module Extractions0a =
+
+    let x = null
+    let result = (x = "") // expect no warning under any configuration
+
+module Extractions0b =
+
+    let x = null
+    let f (x: 'T, y: 'T) = ()
+    let result = f (x, "")   // expect no warning under any configuration
+
+module Extractions0d =
+
+    let x = null
+    let f<'T when 'T : null> (x: 'T, y: 'T) = ()
+    let result = f (x, "")  // expect no warning under any configuration
+
+module Basics =     
+    let x1 : String = null // expect a warning when checknulls is on
+    let x4 : String = ""
+
+module Basics2 = 
+    let f1 () = null
+    let f8 () : String = null  // expect a warning when checknulls is on
+
+type C(s: String) = 
+    member __.Value = s
+
+module InteropBasics =
+    let s0 = String.Concat("a","b")
+    let s1 : String = String.Concat("a","c")
+    let test1()  = String.Concat("a","d")
+    let test2(s1:String, s2: String)  = String.Concat(s1,s2)
+    let test3()  = String( [| 'a' |] )
+    let test4()  = System.AppDomain.CurrentDomain
+    let test5 : System.AppDomain  = System.AppDomain.CurrentDomain
+
+System.Console.WriteLine("a")
+System.Console.WriteLine("a", (null: obj[])) // expect a warning when checknulls is on
+
+let f0 line = 
+    let add (s:String) = ()
+    match line with 
+    | null | "" -> ()
+    | _ -> add line
+
+module NullConstraintTests =
+    type C<'T when 'T : null>() = class end
+
+    let f3 (y : C) = y // expect a warning when checknulls is on
+
+module DefaultValueTests =
+
+    module StructExamples = 
+        []
+        type C1 =
+            []
+            val mutable Whoops : String // expect an error if checknulls is on
+
+        []
+        type C2 =
+            []
+            val mutable Whoops : String // expect no warning or error under any configuration
+
+    module ClassExamples = 
+        type C1 =
+            []
+            val mutable Whoops : String // expect an error if checknulls is on
+
+        type C2 =
+            []
+            val mutable Whoops : String // expect no warning or error under any configuration
+
+        type C4a =
+            []
+            val mutable Whoops : int list // should have given an error in F# 4.5 but didn't, we expect a corrective error if checknulls is on
+
+        type C5 =
+            []
+            val mutable Whoops : int * int // should have given an error in F# 4.5 but didn't, we expect a corrective error if checknulls is on
+
+        type C6 =
+            []
+            val mutable Whoops : int -> int // should have given an error in F# 4.5 but didn't, we expect a corrective error if checknulls is on
+
diff --git a/tests/adhoc/nullness/existing/positive.next.bsl b/tests/adhoc/nullness/existing/positive.next.bsl
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/adhoc/nullness/existing/positive.next.enabled.bsl b/tests/adhoc/nullness/existing/positive.next.enabled.bsl
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/adhoc/nullness/existing/positive.next.enabled.checknulls.bsl b/tests/adhoc/nullness/existing/positive.next.enabled.checknulls.bsl
new file mode 100644
index 00000000000..812c4ba829c
--- /dev/null
+++ b/tests/adhoc/nullness/existing/positive.next.enabled.checknulls.bsl
@@ -0,0 +1,18 @@
+
+tests\adhoc\nullness\existing\positive.fs(23,23): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+
+tests\adhoc\nullness\existing\positive.fs(28,26): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+
+tests\adhoc\nullness\existing\positive.fs(43,32): warning FS3261: Nullness warning: The type 'obj array' is non-null, but a type supporting 'null' is expected.
+
+tests\adhoc\nullness\existing\positive.fs(54,17): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+
+tests\adhoc\nullness\existing\positive.fs(62,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+
+tests\adhoc\nullness\existing\positive.fs(72,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+
+tests\adhoc\nullness\existing\positive.fs(80,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+
+tests\adhoc\nullness\existing\positive.fs(84,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+
+tests\adhoc\nullness\existing\positive.fs(88,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
diff --git a/tests/adhoc/nullness/existing/positive.previous.bsl b/tests/adhoc/nullness/existing/positive.previous.bsl
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/adhoc/nullness/interop/positive.fs b/tests/adhoc/nullness/interop/positive.fs
new file mode 100644
index 00000000000..1358168244f
--- /dev/null
+++ b/tests/adhoc/nullness/interop/positive.fs
@@ -0,0 +1,18 @@
+open System
+
+module Extractions2 =
+
+    let f (x: ActivitySource) =
+       x.CreateActivity("aaa", ActivityKind.Client)
+
+    let source = new ActivitySource("aaab")
+    let activity = f source
+    let baggage = activity.Baggage // TODO NULLNESS: should trigger a nullness warning
+
+    // TODO NULLNESS test matrix
+    // - Import null annotated .NET non-generic type (above)
+    // - Import null annotated .NET array type
+    // - Import null annotated .NET generic type instantiated at non-null .NET type 
+    // - Import .NET generic type instantiated at null annotated .NET type 
+
+
diff --git a/tests/adhoc/nullness/library/positive.fs b/tests/adhoc/nullness/library/positive.fs
new file mode 100644
index 00000000000..6830c8d1e58
--- /dev/null
+++ b/tests/adhoc/nullness/library/positive.fs
@@ -0,0 +1,75 @@
+let failures = ref []
+
+let report_failure (s : string) = 
+    stderr.Write" NO: "
+    stderr.WriteLine s
+    failures.Value <- failures.Value @ [s]
+
+let test (s : string) b = 
+    stderr.Write(s)
+    if b then stderr.WriteLine " OK"
+    else report_failure (s)
+
+let check s b1 b2 = test s (b1 = b2)
+
+module Library =     
+
+    let x5 = nonNull "" // Should not give a Nullness warning
+    check "ekjnceoiwe5" x5 ""
+    let x6 = nonNull "" // **Expected to give a Nullness warning, expected also to give a warning with nullness checking off
+    check "ekjnceoiwe6" x6 ""
+    let x7 = nonNull ""
+    check "ekjnceoiwe7" x7 ""
+    let _x7 : String = x7
+    let x8 = nonNull Array.empty
+    check "ekjnceoiwe8" x8 [| |]
+    let x9 = nonNull [| "" |]
+    check "ekjnceoiwe9" x9 [| "" |]
+    let x10 = nonNullV (Nullable(3))
+    check "ekjnceoiwe10" x10 3
+    let x11 = try nonNullV (Nullable()) with :? System.NullReferenceException -> 10
+    check "ekjnceoiwe11" x11 10
+    let x12 = nullV
+    check "ekjnceoiwe12" x12 (Nullable())
+    let x13 = nullV
+    check "ekjnceoiwe13" x13 (Nullable())
+    let x14 = withNullV 6L
+    check "ekjnceoiwe14" x14 (Nullable(6L))
+    let x15 : String __withnull = withNull x4
+    check "ekjnceoiwe15" x15 ""
+    let x15a : String __withnull = withNull ""
+    check "ekjnceoiwe15a" x15a ""
+    let x15b : String __withnull = withNull x4
+    check "ekjnceoiwe15b" x15b ""
+    let x15c : String __withnull = withNull x4 // **Expected to give a Nullness warning
+    check "ekjnceoiwe15c" x15c ""
+    let x16 : Nullable = withNullV 3
+    check "ekjnceoiwe16" x16 (Nullable(3))
+    
+    let y0 = isNull null // Should not give a Nullness warning (obj)
+    check "ekjnceoiwey0" y0 true
+    let y1 = isNull (null: obj __withnull) // Should not give a Nullness warning
+    check "ekjnceoiwey1" y1 true
+    let y1b = isNull (null: String __withnull) // Should not give a Nullness warning
+    check "ekjnceoiwey1b" y1b true
+    let y2 = isNull "" // **Expected to give a Nullness warning - type instantiation of a nullable type is non-nullable String
+    check "ekjnceoiwey2" y2 false
+    let y9 = isNull "" // **Expected to give a Nullness warning - type instantiation of a nullable type is non-nullable String
+    check "ekjnceoiwey9" y9 false
+    let y10 = isNull "" // Should not give a Nullness warning.
+    check "ekjnceoiwey10" y10 false
+    // Not yet allowed 
+    //let f7 () : 'T __withnull when 'T : struct = null
+    let f7b () : Nullable<'T> = nullV // BUG: Incorrectly gives a warning about System.ValueType with /test:AssumeNullOnImport
+
+    let f0b line = 
+        let add (s:String) = ()
+        match line with 
+        | null  -> ()
+        | _ -> add (nonNull line) // Exected to give a nullness warning
+
+    let add (s:String) = ()
+    let f0c line = 
+        add (nonNull "") // WRONG: should not give a nullness warning
+
+
diff --git a/tests/adhoc/nullness/micro.fs b/tests/adhoc/nullness/micro.fs
new file mode 100644
index 00000000000..d95d0b48ede
--- /dev/null
+++ b/tests/adhoc/nullness/micro.fs
@@ -0,0 +1,9 @@
+
+module M
+
+let isNotNull (value: 'T) = 
+    match value with 
+    | null -> false
+    | _ -> true
+
+let s: System.String = null 
\ No newline at end of file
diff --git a/tests/adhoc/nullness/micro.fsi b/tests/adhoc/nullness/micro.fsi
new file mode 100644
index 00000000000..25271ae6d7e
--- /dev/null
+++ b/tests/adhoc/nullness/micro.fsi
@@ -0,0 +1,3 @@
+
+module M
+val isNotNull: value: 'T -> bool when 'T : null
\ No newline at end of file
diff --git a/tests/fsharp/core/nullness/nullness.fsproj b/tests/adhoc/nullness/nullness.fsproj
similarity index 78%
rename from tests/fsharp/core/nullness/nullness.fsproj
rename to tests/adhoc/nullness/nullness.fsproj
index c8e48a4c144..95d78a3acc1 100644
--- a/tests/fsharp/core/nullness/nullness.fsproj
+++ b/tests/adhoc/nullness/nullness.fsproj
@@ -2,9 +2,6 @@
 
   
     net7.0
-    ..\..\..\..\artifacts\bin\fsc\$(Configuration)\net472
-    fsc.exe
-    
     Exe
     true
     
@@ -16,7 +13,9 @@
   
 
   
-	
+	
+	
+	
   
   
 
diff --git a/tests/adhoc/nullness/validate.cmd b/tests/adhoc/nullness/validate.cmd
new file mode 100644
index 00000000000..2e3e275a9bc
--- /dev/null
+++ b/tests/adhoc/nullness/validate.cmd
@@ -0,0 +1,35 @@
+dotnet build src\fsc\fscProject -f net472 -c Proto -p ProtoDebug=true
+
+fsc.exe tests\adhoc\nullness\micro.fs -i
+fsc.exe tests\adhoc\nullness\micro.fsi tests\adhoc\nullness\micro.fs -i
+
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\micro.fs -i
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\micro.fsi tests\adhoc\nullness\micro.fs -i
+
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\micro.fs -i --langversion:preview
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\micro.fsi tests\adhoc\nullness\micro.fs -i --langversion:preview
+
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\micro.fs -i --langversion:preview --checknulls
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\micro.fsi tests\adhoc\nullness\micro.fs -i --langversion:preview --checknulls
+
+REM -------------
+
+
+fsc.exe tests\adhoc\nullness\existing\positive.fs 2> tests\adhoc\nullness\existing\positive.previous.bsl & type tests\adhoc\nullness\existing\positive.previous.bsl 
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\existing\positive.fs 2>  tests\adhoc\nullness\existing\positive.next.bsl & type tests\adhoc\nullness\existing\positive.next.bsl
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\existing\positive.fs --langversion:preview 2>  tests\adhoc\nullness\existing\positive.next.enabled.bsl & type tests\adhoc\nullness\existing\positive.next.enabled.bsl
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\existing\positive.fs --langversion:preview --checknulls 2>  tests\adhoc\nullness\existing\positive.next.enabled.checknulls.bsl & type tests\adhoc\nullness\existing\positive.next.enabled.checknulls.bsl
+
+fsc.exe tests\adhoc\nullness\existing\negative.fs 2> tests\adhoc\nullness\existing\negative.previous.bsl & type tests\adhoc\nullness\existing\negative.previous.bsl
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\existing\negative.fs 2>  tests\adhoc\nullness\existing\negative.next.bsl & type tests\adhoc\nullness\existing\negative.next.bsl
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\existing\negative.fs --langversion:preview 2>  tests\adhoc\nullness\existing\negative.next.enabled.bsl & type tests\adhoc\nullness\existing\negative.next.enabled.bsl
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\existing\negative.fs --langversion:preview --checknulls 2>  tests\adhoc\nullness\existing\negative.next.enabled.checknulls.bsl & type tests\adhoc\nullness\existing\negative.next.enabled.checknulls.bsl
+
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\enabled\positive.fs 2>  tests\adhoc\nullness\enabled\positive.next.bsl & type tests\adhoc\nullness\enabled\positive.next.bsl
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\enabled\positive.fs --langversion:preview 2>  tests\adhoc\nullness\enabled\positive.next.enabled.bsl & type tests\adhoc\nullness\enabled\positive.next.enabled.bsl
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\enabled\positive.fs --langversion:preview --checknulls 2>  tests\adhoc\nullness\enabled\positive.next.enabled.checknulls.bsl & type tests\adhoc\nullness\enabled\positive.next.enabled.checknulls.bsl
+
+
+REM -------------
+
+artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\test.fsx -i --langversion:preview
diff --git a/tests/fsharp/core/nullness/test.fsx b/tests/fsharp/core/nullness/test.fsx
deleted file mode 100644
index bebdb7a1c0e..00000000000
--- a/tests/fsharp/core/nullness/test.fsx
+++ /dev/null
@@ -1,450 +0,0 @@
-let failures = ref []
-
-let report_failure (s : string) = 
-    stderr.Write" NO: "
-    stderr.WriteLine s
-    failures := !failures @ [s]
-
-let test (s : string) b = 
-    stderr.Write(s)
-    if b then stderr.WriteLine " OK"
-    else report_failure (s)
-
-let check s v1 v2 = test s (v1 = v2)
-
-open System
-open System.Diagnostics
-open System.Runtime.CompilerServices
-
-
-module Extractions0a =
-
-    let x = null
-    let result = (x = "") // expect no warning
-
-module Extractions0b =
-
-    let x = null
-    let f (x: 'T, y: 'T) = ()
-    let result = f (x, "")   // expect no warning
-
-#if NEGATIVE
-// This give a warning since 'T is not known to be reference type non-null
-let f<'T> (x: 'T __withnull, y: 'T __withnull) = ()
-#endif
-
-module Extractions0c =
-
-    let x = null
-    let f<'T when 'T : __notnull> (x: 'T __withnull, y: 'T __withnull) = ()
-    let s : string = ""
-    let result = f (x, s)   // expect no warning
-
-module Extractions0d =
-
-    let x = null
-    let f<'T when 'T : null> (x: 'T, y: 'T) = ()
-    let result = f (x, "")  // expect no warning
-
-module Extractions0e =
-
-    let x = null
-    let f<'T when 'T : __notnull> (x: 'T __withnull, y: 'T __withnull) = ()
-    let result = f (x, "") // expect no warning
-
-module Extractions1 =
-
-    let mutable x : _ __withnull = null
-    x <- ""  // expect no warning
-
-module Extractions2 =
-    open System.Diagnostics
-
-    let f (x: ActivitySource) =
-       x.CreateActivity("aaa", ActivityKind.Client)
-
-    let source = new ActivitySource("aaab")
-    let activity = f source
-    let baggage = activity.Baggage // TODO NULLNESS: should trigger a nullness warning
-
-    // TODO NULLNESS test matrix
-    // - Import null annotated .NET non-generic type (above)
-    // - Import null annotated .NET array type
-    // - Import null annotated .NET generic type instantiated at non-null .NET type 
-    // - Import .NET generic type instantiated at null annotated .NET type 
-
-
-//let f<'T when 'T : not struct> (x: 'T __withnull) = 1
-
-(*
-module Basics =     
-    let x1 : string = null // ** Expected to give a Nullness warning
-    check "ekjnceoiwe1" x1 null // ** Expected to give a Nullness warning
-    let x2 : string __withnull = null
-    check "ekjnceoiwe2" x2 null
-    let x3 : string __withnull = "a"
-    check "ekjnceoiwe3" x3 "a"
-    let x4 : string = ""
-    check "ekjnceoiwe4" x4 ""
-
-    let x5 = nonNull "" // Should not give a Nullness warning
-    check "ekjnceoiwe5" x5 ""
-    let x6 = nonNull "" // **Expected to give a Nullness warning, expected also to give a warning with nullness checking off
-    check "ekjnceoiwe6" x6 ""
-    let x7 = nonNull ""
-    check "ekjnceoiwe7" x7 ""
-    let _x7 : string = x7
-    let x8 = nonNull Array.empty
-    check "ekjnceoiwe8" x8 [| |]
-    let x9 = nonNull [| "" |]
-    check "ekjnceoiwe9" x9 [| "" |]
-    let x10 = nonNullV (Nullable(3))
-    check "ekjnceoiwe10" x10 3
-    let x11 = try nonNullV (Nullable()) with :? System.NullReferenceException -> 10
-    check "ekjnceoiwe11" x11 10
-    let x12 = nullV
-    check "ekjnceoiwe12" x12 (Nullable())
-    let x13 = nullV
-    check "ekjnceoiwe13" x13 (Nullable())
-    let x14 = withNullV 6L
-    check "ekjnceoiwe14" x14 (Nullable(6L))
-    let x15 : string __withnull = withNull x4
-    check "ekjnceoiwe15" x15 ""
-    let x15a : string __withnull = withNull ""
-    check "ekjnceoiwe15a" x15a ""
-    let x15b : string __withnull = withNull x4
-    check "ekjnceoiwe15b" x15b ""
-    let x15c : string __withnull = withNull x4 // **Expected to give a Nullness warning
-    check "ekjnceoiwe15c" x15c ""
-    let x16 : Nullable = withNullV 3
-    check "ekjnceoiwe16" x16 (Nullable(3))
-    
-    let y0 = isNull null // Should not give a Nullness warning (obj)
-    check "ekjnceoiwey0" y0 true
-    let y1 = isNull (null: obj __withnull) // Should not give a Nullness warning
-    check "ekjnceoiwey1" y1 true
-    let y1b = isNull (null: string __withnull) // Should not give a Nullness warning
-    check "ekjnceoiwey1b" y1b true
-    let y2 = isNull "" // **Expected to give a Nullness warning - type instantiation of a nullable type is non-nullable string
-    check "ekjnceoiwey2" y2 false
-    let y9 = isNull "" // **Expected to give a Nullness warning - type instantiation of a nullable type is non-nullable string
-    check "ekjnceoiwey9" y9 false
-    let y10 = isNull "" // Should not give a Nullness warning.
-    check "ekjnceoiwey10" y10 false
-
-module NotNullConstraint =
-    let f3 (x: 'T when 'T : __notnull) = 1
-    let v1 = f3 1 
-    check "ekjnceoiwev1" v1 1
-    let v2 = f3 "a"
-    check "ekjnceoiwev2" v2 1
-    let v3 = f3 (null: obj __withnull) // Expect to give a warning
-    check "ekjnceoiwev3" v3 1
-    let v4 = f3 (null: string __withnull) // Expect to give a warning
-    check "ekjnceoiwev4" v4 1
-#if NEGATIVE
-    f3 (Some 1) // Expect to give an error
-#endif
-
-    let w1 = 1 |> f3
-    check "ekjnceoiwew1" w1 1
-    let w2 = "a" |> f3
-    check "ekjnceoiwew2" w2 1
-    let w3 = (null: obj __withnull) |> f3 // Expect to give a warning
-    check "ekjnceoiwew3" w3 1
-    let w4 = (null: string __withnull) |> f3 // Expect to give a warning
-    check "ekjnceoiwew4" w4 1
-
-module MemberBasics = 
-    type C() = 
-        member x.P = 1
-        member x.M() = 2
-
-    let c : C __withnull = C()
-    let v1 = c.P  // Expected to give a warning
-    check "ekjnccwwecv1" v1 1
-    let v2 = c.M()  // Expected to give a warning
-    check "ekjnccwwecv2" v2 2
-    let f1 = c.M  // Expected to give a warning
-    check "ekjnccwwecv3" (f1()) 2
-
-module Basics2 = 
-    let f1 () = null
-    // val f : unit -> 'a when 'a : null
-
-    let f2 () : string __withnull = null
-    // val f : unit -> string __withnull
-
-    let f3 () : 'T __withnull = null
-
-    let f4 () : 'T __withnull when 'T : not struct = null
-
-    let f5 () : 'T when 'T : not struct and 'T : null = null
-
-#if NEGATIVE
-    let f6 () : 'T __withnull when 'T : not struct and 'T : null = null // Expected to give an error about inconistent constraints
-#endif
-
-    // Note yet allowed 
-    //let f7 () : 'T __withnull when 'T : struct = null
-    let f7b () : Nullable<'T> = nullV // BUG: Incorrectly gives a warning about System.ValueType with /test:AssumeNullOnImport
-
-    let f8 () : string = null // Expected to give a Nullness warning
-
-type C(s: string) = 
-    member __.Value = s
-
-module InteropBasics =
-    let s0 = String.Concat("a","b") // Expected to infer string __withnull with /test:AssumeNullOnImport
-    check "ekjnccberpos0" s0 "ab"
-    let s1 : string = String.Concat("a","c") // Expected to gives a warning with /test:AssumeNullOnImport
-    check "ekjnccberpos0" s1 "ac"
-    let test1()  = String.Concat("a","d")
-    check "ekjnccberpos0" (test1()) "ad"
-    let test2(s1:string, s2: string)  = String.Concat(s1,s2)
-    let test3()  = String( [| 'a' |] )
-    let test4()  = System.AppDomain.CurrentDomain
-    let test5 : System.AppDomain  = System.AppDomain.CurrentDomain // Expected to gives a warning with /test:AssumeNullOnImport
-
-type KonsoleWithNulls = 
-    static member WriteLine(s: string __withnull) = Console.WriteLine(s)
-    static member WriteLine(fmt: string __withnull, arg1: string __withnull) = Console.WriteLine(fmt, arg1)
-    static member WriteLine(fmt: string __withnull, [] args: obj __withnull[] __withnull) = Console.WriteLine(fmt, args)
-    static member WriteLineC(s: C __withnull) = Console.WriteLine(s.Value)
-    static member WriteLineC(fmt: C __withnull, arg1: C __withnull) = Console.WriteLine(fmt.Value, arg1.Value)
-
-module KonsoleWithNullsModule = 
-    let WriteLine(s: string __withnull) = Console.WriteLine(s)
-    let WriteLine2(fmt: string __withnull, arg1: string __withnull) = Console.WriteLine(fmt, arg1)
-    let WriteLineC(s: C __withnull) = Console.WriteLine(s.Value)
-    let WriteLineC2(fmt: C __withnull, arg1: C __withnull) = Console.WriteLine(fmt.Value, arg1.Value)
-
-module KonsoleWithNullsModule2 = 
-    let WriteLine x = KonsoleWithNullsModule.WriteLine x
-    let WriteLine2 (fmt, arg1) = KonsoleWithNullsModule.WriteLine2(fmt, arg1)
-    let WriteLineC(s) = KonsoleWithNullsModule.WriteLineC(s)
-    let WriteLineC2(fmt, arg1) = KonsoleWithNullsModule.WriteLineC2(fmt, arg1)
-
-type KonsoleNoNulls = 
-    static member WriteLine(s: string) = Console.WriteLine(s)
-    static member WriteLine(fmt: string, arg1: string __withnull) = Console.WriteLine(fmt, arg1)
-    static member WriteLine(fmt: string, [] args: obj[]) = Console.WriteLine(fmt, args)
-    static member WriteLineC(s: C) = Console.WriteLine(s.Value)
-    static member WriteLineC(fmt: C, arg1: C) = Console.WriteLine(fmt.Value, arg1.Value)
-
-module KonsoleNoNullsModule = 
-    let WriteLine(s: string) = Console.WriteLine(s)
-    let WriteLine2(fmt: string, arg1: string) = Console.WriteLine(fmt, arg1)
-    let WriteLineC(s: C) = Console.WriteLine(s.Value)
-    let WriteLineC2(fmt: C, arg1: C) = Console.WriteLine(fmt.Value, arg1.Value)
-
-module KonsoleNoNullsModule2 = 
-    let WriteLine x = KonsoleNoNullsModule.WriteLine x
-    let WriteLine2 (fmt, arg1) = KonsoleNoNullsModule.WriteLine2(fmt, arg1)
-    let WriteLineC(s) = KonsoleNoNullsModule.WriteLineC(s)
-    let WriteLineC2(fmt, arg1) = KonsoleNoNullsModule.WriteLineC2(fmt, arg1)
-
-System.Console.WriteLine("a")
-System.Console.WriteLine("a", (null: obj[])) // Expected to give a Nullness warning
-
-KonsoleWithNulls.WriteLine("Hello world")
-KonsoleWithNulls.WriteLine(null) // WRONG: gives an incorrect Nullness warning for string __withnull and string __withnull
-KonsoleWithNulls.WriteLine("Hello","world")
-KonsoleWithNulls.WriteLine("Hello","world","there") // // WRONG: gives an incorrect Nullness warning for string __withnull and string __withnull
-
-KonsoleNoNulls.WriteLine("Hello world")
-try 
-   KonsoleNoNulls.WriteLine(null)  // Expected to give a Nullness warning
-with :? System.ArgumentNullException -> ()
-KonsoleNoNulls.WriteLine("Hello","world")
-//KonsoleNoNulls.WriteLine("Hello",null) // CHECK ME 
-try 
-    KonsoleNoNulls.WriteLine(null, "World")   // Expected to give a Nullness warning
-with :? System.ArgumentNullException -> ()
-
-KonsoleWithNullsModule.WriteLine("Hello world")
-try 
-    KonsoleWithNullsModule.WriteLine(null) 
-with :? System.ArgumentNullException -> ()
-KonsoleWithNullsModule.WriteLine2("Hello","world") 
-KonsoleWithNullsModule.WriteLine2("Hello",null)
-try
-    KonsoleWithNullsModule.WriteLine2(null,"world")
-with :? System.ArgumentNullException -> ()
-
-KonsoleWithNullsModule2.WriteLine("Hello world")
-try 
-    KonsoleWithNullsModule2.WriteLine(null) 
-with :? System.ArgumentNullException -> ()
-KonsoleWithNullsModule2.WriteLine2("Hello","world")
-KonsoleWithNullsModule2.WriteLine2("Hello",null)
-try 
-    KonsoleWithNullsModule2.WriteLine2(null,"world")
-with :? System.ArgumentNullException -> ()
-
-KonsoleNoNullsModule.WriteLine("Hello world")
-try 
-    KonsoleNoNullsModule.WriteLine(null)  // Expected to give a Nullness warning
-with :? System.ArgumentNullException -> ()
-KonsoleNoNullsModule.WriteLine2("Hello","world")
-KonsoleNoNullsModule.WriteLine2("Hello",null) // Expected to give a Nullness warning
-try 
-    KonsoleNoNullsModule.WriteLine2(null,"world") // Expected to give a Nullness warning
-with :? System.ArgumentNullException -> ()
-
-//-------------------------------------
-
-// Param array cases
-
-KonsoleNoNulls.WriteLine("Hello","world","there")
-KonsoleWithNulls.WriteLine("Hello","world",null)  // Expected to give a Nullness warning 
-KonsoleNoNulls.WriteLine("Hello","world",null)  // Expected to give a Nullness warning
-System.Console.WriteLine("a", (null: obj[] __withnull)) 
-System.Console.WriteLine("a", (null: obj __withnull[] __withnull))
-
-//-------
-// random stuff
-
-let f0 line = 
-    let add (s:string) = ()
-    match line with 
-    | null | "" -> ()
-    | _ -> add line // Exected to give a nullness warning
-
-let f0b line = 
-    let add (s:string) = ()
-    match line with 
-    | null  -> ()
-    | _ -> add (nonNull line) // Exected to give a nullness warning
-
-let add (s:string) = ()
-let f0c line = 
-    add (nonNull "") // WRONG: should not give a nullness warning
-
-//let f2 (x: string or null) = x;;
-let f3 (x: string __withnull) = x
-let f5 x = (x: int)
-//let f4 x = (x: string nullable)
-
-//let f6<'T when 'T : __notnull> (x: 'T) = x
-//let f6<'T when 'T : __notnull> (x: 'T) = x
-
-//let f2 (x: string | null) = x;;
-
-//let f2 (_x : string | null) = x;;
-
-//let f2 (x: (string | null)) = x;;
-
-//let f3 x = (x: (string | null))
-
-module NullConstraintTests =
-    type C<'T when 'T : null>() = class end
-
-#if NEGATIVE
-    let f1 (y : C< (int * int) >) = y // This gave an error in F# 4.5 and we expect it to continue to give an error
-
-#endif
-
-#if CHECKNULLS
-     // This gave an error in F# 4.5.  It now only gives a warning when --checknulls is on which is sort of ok
-     // since we are treating .NET and F# types more symmetrically.
-     //
-     // TODO: However it gives no error or warning at all with --checknulls off in F# 5.0...  That seems bad.
-    let f2 (y : C) = y
-
-    let f3 (y : C) = y // Expect a Nullness warning
-
-    let f4 (y : C) = y // No warning expected 
-
-    let f5 (y : C) = y // No warning expected
-
-    let f6 (y : C __withnull>) = y // No warning expected, lexing/parsing should succeed 
-
-    let f7 (y : C> __withnull) = y // No warning expected, lexing/parsing should succeed
-#endif
-
-
-module DefaultValueTests =
-
-
-    module StructExamples = 
-        []
-        type C1 =
-            []
-            val mutable Whoops : string // expect a warning
-
-        []
-        type C2 =
-            []
-            val mutable Whoops : string // expect no warning
-
-        []
-        type C3 =
-            []
-            val mutable Whoops : string __withnull // expect no warning
-
-#if NEGATIVE
-        []
-        type C4a =
-            []
-            val mutable Whoops : int list // expect a hard error like in F# 4.5
-#endif
-
-        []
-        type C4b =
-            []
-            val mutable Whoops : int list __withnull // expect no warning
-
-#if NEGATIVE
-        []
-        type C5 =
-            []
-            val mutable Whoops : int * int // expect an error like F# 4.5
-
-        []
-        type C6 =
-            []
-            val mutable Whoops : int -> int // expect an error like F# 4.5
-#endif
-
-        []
-        type C7 =
-            []
-            val mutable Whoops : (int -> int) __withnull // expect no warning
-
-    module ClassExamples = 
-        type C1 =
-            []
-            val mutable Whoops : string // expect a warning
-
-        type C2 =
-            []
-            val mutable Whoops : string // expect no warning
-
-        type C3 =
-            []
-            val mutable Whoops : string __withnull // expect no warning
-
-        type C4a =
-            []
-            val mutable Whoops : int list // ** expect a warning
-
-        type C4b =
-            []
-            val mutable Whoops : int list __withnull // expect no warning
-
-    #if NEGATIVE
-        type C5 =
-            []
-            val mutable Whoops : int * int // expect an error like F# 4.5
-
-        type C6 =
-            []
-            val mutable Whoops : int -> int // expect an error like F# 4.5
-    #endif
-
-        type C7 =
-            []
-            val mutable Whoops : (int -> int) __withnull // expect no warning
-*)
-

From 74042c767fc626aace191224193cfcc0d213d00d Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Wed, 24 May 2023 22:46:47 +0100
Subject: [PATCH 04/59] fix up constraint solving and adhoc testing

---
 src/Compiler/Checking/ConstraintSolver.fs     | 36 ++++++++-
 src/Compiler/FSStrings.resx                   |  6 +-
 src/Compiler/TypedTree/TypedTreeOps.fs        | 26 +++++--
 src/Compiler/TypedTree/TypedTreeOps.fsi       |  2 +-
 src/Compiler/xlf/FSComp.txt.cs.xlf            | 18 +----
 src/Compiler/xlf/FSComp.txt.de.xlf            | 18 +----
 src/Compiler/xlf/FSComp.txt.es.xlf            | 18 +----
 src/Compiler/xlf/FSComp.txt.fr.xlf            | 18 +----
 src/Compiler/xlf/FSComp.txt.it.xlf            | 18 +----
 src/Compiler/xlf/FSComp.txt.ja.xlf            | 18 +----
 src/Compiler/xlf/FSComp.txt.ko.xlf            | 18 +----
 src/Compiler/xlf/FSComp.txt.pl.xlf            | 18 +----
 src/Compiler/xlf/FSComp.txt.pt-BR.xlf         | 18 +----
 src/Compiler/xlf/FSComp.txt.ru.xlf            | 18 +----
 src/Compiler/xlf/FSComp.txt.tr.xlf            | 18 +----
 src/Compiler/xlf/FSComp.txt.zh-Hans.xlf       | 18 +----
 src/Compiler/xlf/FSComp.txt.zh-Hant.xlf       | 18 +----
 src/Compiler/xlf/FSStrings.cs.xlf             | 18 ++---
 src/Compiler/xlf/FSStrings.de.xlf             | 18 ++---
 src/Compiler/xlf/FSStrings.es.xlf             | 18 ++---
 src/Compiler/xlf/FSStrings.fr.xlf             | 18 ++---
 src/Compiler/xlf/FSStrings.it.xlf             | 18 ++---
 src/Compiler/xlf/FSStrings.ja.xlf             | 18 ++---
 src/Compiler/xlf/FSStrings.ko.xlf             | 18 ++---
 src/Compiler/xlf/FSStrings.pl.xlf             | 18 ++---
 src/Compiler/xlf/FSStrings.pt-BR.xlf          | 18 ++---
 src/Compiler/xlf/FSStrings.ru.xlf             | 18 ++---
 src/Compiler/xlf/FSStrings.tr.xlf             | 18 ++---
 src/Compiler/xlf/FSStrings.zh-Hans.xlf        | 18 ++---
 src/Compiler/xlf/FSStrings.zh-Hant.xlf        | 18 ++---
 src/FSharp.Core/seqcore.fs                    |  2 +-
 tests/adhoc/nullness/enabled/negative.fs      | 51 ++++++++++++
 tests/adhoc/nullness/enabled/positive.fs      | 49 +-----------
 .../adhoc/nullness/enabled/positive.next.bsl  | 12 +--
 .../enabled/positive.next.enabled.bsl         | 14 +---
 .../positive.next.enabled.checknulls.bsl      | 48 +++++-------
 tests/adhoc/nullness/existing/negative.fs     | 77 +++----------------
 .../adhoc/nullness/existing/negative.next.bsl |  2 +
 .../existing/negative.next.enabled.bsl        |  2 +
 .../negative.next.enabled.checknulls.bsl      | 16 ++--
 .../nullness/existing/negative.previous.bsl   |  2 +
 tests/adhoc/nullness/existing/positive.fs     | 22 +-----
 .../positive.next.enabled.checknulls.bsl      | 18 +----
 tests/adhoc/nullness/nullness.fsproj          |  4 +-
 tests/adhoc/nullness/validate.cmd             |  5 +-
 45 files changed, 341 insertions(+), 521 deletions(-)

diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs
index 40f7747e3a2..366844c6a18 100644
--- a/src/Compiler/Checking/ConstraintSolver.fs
+++ b/src/Compiler/Checking/ConstraintSolver.fs
@@ -2457,7 +2457,38 @@ and AddConstraint (csenv: ConstraintSolverEnv) ndeep m2 trace tp newConstraint
             ()
     }
 
-// This version prefers to constrain the nullness annotation for a type annotation usage
+// preferConstraint: if the type is a type variable with an uncertain nullness, then
+// this indicates whether we prefer to add a nullness constraint to the type variable itself,
+// or whether we prefer to solve the nullness annotation.
+//
+// This is relevant for code like this:
+//
+//    let isNull (value : 'T when 'T : null) = 
+//        match box value with 
+//        | null -> true 
+//        | _ -> false
+//
+//    let checkNonNull argName arg =
+//        if isNull arg then
+//            failwith (argName + " is null")
+//
+// Here the `'T: null` constraint is propagated by inference to checkNonNull. Which of these two types do we expect?
+//
+//    val checkNonNull1: argName: string -> arg: 'T -> unit when 'T: null
+//
+//    val checkNonNull2: argName: string -> arg: 'T __withnull -> unit
+//
+// When null checking is fully enabled, we prefer the latter. We can't always prefer it because it is a breaking change.
+//
+// Likewise consider
+//
+//    let x = null
+//
+// What's the generalized type?
+//    val x: 'a when 'a: null
+//    val x: 'a __withnull when 'a: not null
+//
+// When null checking is fully enabled, we prefer the latter. We can't always prefer it because it is a breaking change.
 and SolveTypeUseSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 trace ty = trackErrors {
     let g = csenv.g
     let m = csenv.m
@@ -2470,9 +2501,10 @@ and SolveTypeUseSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 trace ty = tra
         else
             match tryDestTyparTy g ty with
             | ValueSome tp ->
-                do! SolveTypeIsReferenceType csenv ndeep m2 trace ty
                 let nullness = nullnessOfTy g ty
                 match nullness.TryEvaluate() with
+                | ValueNone when not g.checkNullness ->
+                    return! AddConstraint csenv ndeep m2 trace tp (TyparConstraint.SupportsNull m)
                 | ValueSome NullnessInfo.WithoutNull ->
                     return! AddConstraint csenv ndeep m2 trace tp (TyparConstraint.SupportsNull m)
                 | _ ->
diff --git a/src/Compiler/FSStrings.resx b/src/Compiler/FSStrings.resx
index 83a8b332faf..bbd5b912219 100644
--- a/src/Compiler/FSStrings.resx
+++ b/src/Compiler/FSStrings.resx
@@ -130,13 +130,13 @@
     A type parameter is missing a constraint '{0}'
   
   
-    Nullness warning: A non-null type is expected. The types '{0}' and '{1}' do not have equivalent nullability.
+    Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
   
   
-    Nullness warning: A non-null type is expected. The types '{0}' and '{1}' do not have compatible nullability.
+    Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
   
   
-    Nullness warning: The type '{0}' is non-null, but a type supporting 'null' is expected.
+    Nullness warning: The type '{0}' does not support 'null'.
   
   
     Nullness warning: {0}.
diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs
index 2b4e5af995c..d884826c2e2 100644
--- a/src/Compiler/TypedTree/TypedTreeOps.fs
+++ b/src/Compiler/TypedTree/TypedTreeOps.fs
@@ -8882,15 +8882,24 @@ let isNonNullableStructTyparTy g ty =
     | ValueNone ->
         false
 
-// Note, isRefTy does not include type parameters with the ': not struct' constraint
+// Note, isRefTy does not include type parameters with the ': not struct' or ': null' constraints
 // This predicate is used to detect those type parameters.
 let isReferenceTyparTy g ty = 
     match tryDestTyparTy g ty with 
     | ValueSome tp -> 
-        tp.Constraints |> List.exists (function TyparConstraint.IsReferenceType _ -> true | _ -> false)
+        tp.Constraints |> List.exists (function
+            | TyparConstraint.IsReferenceType _ -> true
+            | TyparConstraint.SupportsNull _ -> true
+            | _ -> false)
     | ValueNone ->
         false
 
+let isSupportsNullTyparTy g ty = 
+    if isReferenceTyparTy g ty then
+        (destTyparTy g ty).Constraints |> List.exists (function TyparConstraint.SupportsNull _ -> true | _ -> false)
+    else
+        false
+
 let TypeNullNever g ty = 
     let underlyingTy = stripTyEqnsAndMeasureEqns g ty
     isStructTy g underlyingTy ||
@@ -8917,16 +8926,16 @@ let TypeNullIsExtraValue g m ty =
         | ValueNone -> 
 
         // Consider type parameters
-        if isReferenceTyparTy g ty then
-            (destTyparTy g ty).Constraints |> List.exists (function TyparConstraint.SupportsNull _ -> true | _ -> false)
-        else
-            false
+        isSupportsNullTyparTy g ty
 
 /// The new logic about whether a type admits the use of 'null' as a value.
 let TypeNullIsExtraValueNew g m ty = 
     let sty = stripTyparEqns ty
+
+    // Check if the type is 'obj'
     isObjTy g sty
     ||
+    // Check if the type has AllowNullLiteral
     (match tryTcrefOfAppTy g sty with 
      | ValueSome tcref -> 
         not tcref.IsStructOrEnumTycon &&
@@ -8934,13 +8943,14 @@ let TypeNullIsExtraValueNew g m ty =
         (TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref = Some true)
      | _ -> false) 
     ||
+    // Check if the type has a nullness annotation
     (match (nullnessOfTy g sty).Evaluate() with 
      | NullnessInfo.AmbivalentToNull -> false
      | NullnessInfo.WithoutNull -> false
      | NullnessInfo.WithNull -> true)
     ||
-    (isReferenceTyparTy g ty &&
-     (destTyparTy g ty).Constraints |> List.exists (function TyparConstraint.SupportsNull _ -> true | _ -> false))
+    // Check if the type has a ': null' constraint
+    isSupportsNullTyparTy g ty
 
 /// The F# 4.5 and 5.0 logic about whether a type uses 'null' as a true representation value
 let TypeNullIsTrueValue g ty =
diff --git a/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi
index 514c778a4b6..db8d887358a 100755
--- a/src/Compiler/TypedTree/TypedTreeOps.fsi
+++ b/src/Compiler/TypedTree/TypedTreeOps.fsi
@@ -1654,7 +1654,7 @@ val isFSharpDelegateTy: TcGlobals -> TType -> bool
 /// Determine if a type is an interface type
 val isInterfaceTy: TcGlobals -> TType -> bool
 
-/// Determine if a type is a FSharpRef type
+/// Determine if a type is a reference type
 val isRefTy: TcGlobals -> TType -> bool
 
 /// Determine if a type is a function (including generic). Not the same as isFunTy.
diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf
index 0c35b2fb1a1..305bdfcb5ac 100644
--- a/src/Compiler/xlf/FSComp.txt.cs.xlf
+++ b/src/Compiler/xlf/FSComp.txt.cs.xlf
@@ -92,11 +92,6 @@
         Použití incr z knihovny F# je zastaralé. Více informací: https://aka.ms/fsharp-refcell-ops. Změňte prosím například incr cell na cell.Value <- cell.Value + 1.
         
       
-      
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        
-      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Pokud typ používá atribut [<Sealed>] i [<AbstractClass>], znamená to, že je statický. Členové instance nejsou povoleni.
@@ -178,13 +173,13 @@
         
       
       
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
         
       
       
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
         
       
       
@@ -1002,11 +997,6 @@
         Atributy nejde použít pro rozšíření typů.
         
       
-      
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        
-      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Tento výraz záznamu kopírování a aktualizace mění všechna pole typu záznamu '{0}'. Zvažte použití syntaxe konstrukce záznamu.
diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf
index be02e5e8b23..7bd9908e563 100644
--- a/src/Compiler/xlf/FSComp.txt.de.xlf
+++ b/src/Compiler/xlf/FSComp.txt.de.xlf
@@ -92,11 +92,6 @@
         Die Verwendung von "incr" aus der F#-Bibliothek ist veraltet. Siehe https://aka.ms/fsharp-refcell-ops. Ändern Sie z. B. "incr cell" in "cell.Value <- cell.Value + 1".
         
       
-      
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        
-      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Wenn ein Typ sowohl das Attribute [<Sealed>] wie auch [<AbstractClass>] verwendet, bedeutet dies, dass er statisch ist. Let-Bindungen der Instanz sind nicht zulässig.
@@ -178,13 +173,13 @@
         
       
       
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
         
       
       
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
         
       
       
@@ -1002,11 +997,6 @@
         Attribute können nicht auf Typerweiterungen angewendet werden.
         
       
-      
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        
-      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Dieser Ausdruck zum Kopieren und Aktualisieren von Datensätzen ändert alle Felder des Datensatztyps "{0}". Erwägen Sie stattdessen die Verwendung der Datensatzerstellungssyntax.
diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf
index b840c9cf4f3..e8766233b1f 100644
--- a/src/Compiler/xlf/FSComp.txt.es.xlf
+++ b/src/Compiler/xlf/FSComp.txt.es.xlf
@@ -92,11 +92,6 @@
         El uso de "incr" de la biblioteca de F# está en desuso. Vea https://aka.ms/fsharp-refcell-ops. Por ejemplo, cambie "incr cell" a "cell.Value <- cell.Value + 1".
         
       
-      
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        
-      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Si un tipo utiliza ambos atributos [<Sealed>] y [<AbstractClass>], significa que es estático. No se permiten los enlaces let de instancia.
@@ -178,13 +173,13 @@
         
       
       
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
         
       
       
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
         
       
       
@@ -1002,11 +997,6 @@
         Los atributos no se pueden aplicar a las extensiones de tipo.
         
       
-      
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        
-      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Esta expresión de copia y actualización de registros cambia todos los campos de tipo de registro "{0}". Es preferible utilizar la sintaxis de construcción de registros.
diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf
index e7ffcb0e4c1..72444d4229f 100644
--- a/src/Compiler/xlf/FSComp.txt.fr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.fr.xlf
@@ -92,11 +92,6 @@
         L’utilisation de « incr » à partir de la bibliothèque F# est déconseillée. Voir https://aka.ms/fsharp-refcell-ops. Par exemple, veuillez remplacer « incr cell » par « cell.Value <- cell.Value + 1 ».
         
       
-      
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        
-      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Si un type utilise à la fois les attributs [<Sealed>] et [<AbstractClass>], cela signifie qu'il est statique. Les liaisons let d'instance ne sont pas autorisées.
@@ -178,13 +173,13 @@
         
       
       
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
         
       
       
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
         
       
       
@@ -1002,11 +997,6 @@
         Impossible d'appliquer des attributs aux extensions de type.
         
       
-      
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        
-      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Cette expression d'enregistrement de copie et de mise à jour modifie tous les champs du type d'enregistrement '{0}'. Envisagez d'utiliser la syntaxe de construction d'enregistrement à la place.
diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf
index ec86e99587b..4c25b1b6e0a 100644
--- a/src/Compiler/xlf/FSComp.txt.it.xlf
+++ b/src/Compiler/xlf/FSComp.txt.it.xlf
@@ -92,11 +92,6 @@
         L'uso di 'incr' dalla libreria F # è deprecato. Vedere https://aka.ms/fsharp-refcell-ops. Ad esempio, modificare 'incr cell' in 'cell.Value <- cell.Value + 1'.
         
       
-      
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        
-      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Se un tipo usa entrambi gli attributi [<Sealed>] e [<AbstractClass>], significa che è statico. Non sono consentite associazioni let delle istanze.
@@ -178,13 +173,13 @@
         
       
       
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
         
       
       
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
         
       
       
@@ -1002,11 +997,6 @@
         Gli attributi non possono essere applicati a estensioni di tipo.
         
       
-      
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        
-      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Questa espressione di record di copia e aggiornamento modifica tutti i campi del tipo di record '{0}'. Provare a usare la sintassi di costruzione dei record.
diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf
index 39416b6337c..d52c1a2973b 100644
--- a/src/Compiler/xlf/FSComp.txt.ja.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ja.xlf
@@ -92,11 +92,6 @@
         F# ライブラリからの 'incr' の使用は非推奨です。https://aka.ms/fsharp-refcell-ops を参照してください。たとえば、'incr cell' を 'cell.Value <- cell.Value +1' に変更してください。
         
       
-      
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        
-      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         型が [<Sealed>] と [<AbstractClass>] の両方の属性を使用する場合、それは静的であることを意味します。インスタンス let バインドは許可されません。
@@ -178,13 +173,13 @@
         
       
       
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
         
       
       
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
         
       
       
@@ -1002,11 +997,6 @@
         属性を型拡張に適用することはできません。
         
       
-      
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        
-      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         この copy-and-update レコード式は、レコードの種類が '{0}' であるすべてのフィールドを変更します。代わりにレコード構築構文を使用することを検討してください。
diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf
index 607b67baaed..8f1a1e287ef 100644
--- a/src/Compiler/xlf/FSComp.txt.ko.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ko.xlf
@@ -92,11 +92,6 @@
         F# 라이브러리의 'incr' 사용은 더 이상 사용되지 않습니다. https://aka.ms/fsharp-refcell-ops를 참조하세요. 예를 들어 'incr cell'을 'cell.Value <- cell.Value + 1'로 변경하세요.
         
       
-      
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        
-      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         형식이 [<Sealed>] 및 [<AbstractClass>] 특성을 모두 사용하는 경우 정적임을 의미합니다. 인스턴스 let 바인딩은 허용되지 않습니다.
@@ -178,13 +173,13 @@
         
       
       
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
         
       
       
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
         
       
       
@@ -1002,11 +997,6 @@
         형식 확장에 특성을 적용할 수 없습니다.
         
       
-      
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        
-      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         이 레코드 복사 및 업데이트 식은 '{0}' 레코드 형식의 모든 필드를 변경합니다. 레코드 생성 구문을 대신 사용하는 것이 좋습니다.
diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf
index f33dd980b7d..2a16d8179bc 100644
--- a/src/Compiler/xlf/FSComp.txt.pl.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pl.xlf
@@ -92,11 +92,6 @@
         Użycie elementu „incr” z biblioteki języka F# jest przestarzałe. Sprawdź stronę https://aka.ms/fsharp-refcell-ops. Na przykład zmień wyrażenie „incr cell” na „cell.Value <- cell.Value + 1”.
         
       
-      
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        
-      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Jeśli typ używa obu atrybutów [<Sealed>] i [< AbstractClass>], oznacza to, że jest on statyczny. Połączenia let wystąpienia są niedozwolone.
@@ -178,13 +173,13 @@
         
       
       
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
         
       
       
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
         
       
       
@@ -1002,11 +997,6 @@
         Atrybutów nie można stosować do rozszerzeń typu.
         
       
-      
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        
-      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         To wyrażenie rekordu kopiowania i aktualizacji zmienia wszystkie pola typu rekordu „{0}”. Zamiast tego rozważ użycie składni konstrukcji rekordu.
diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
index f7a8891e84d..fd8ae9dd349 100644
--- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
@@ -92,11 +92,6 @@
         O uso de 'incr' da biblioteca F# foi preterido. Consulte https://aka.ms/fsharp-refcell-ops. Por exemplo, altere a célula 'incr cell' para 'cell.Value <- cell.Value + 1'.
         
       
-      
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        
-      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Se um tipo usar os atributos [<Sealed>] e [<AbstractClass>], isso significará que ele é estático. Associações de permissão de instância não são permitidas.
@@ -178,13 +173,13 @@
         
       
       
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
         
       
       
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
         
       
       
@@ -1002,11 +997,6 @@
         Os atributos não podem ser aplicados às extensões de tipo.
         
       
-      
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        
-      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Essa expressão de registro copiar e atualizar altera todos os campos do tipo de registro '{0}'. Considere usar a sintaxe de construção de registro em vez disso.
diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf
index 4e75473322b..2308c960145 100644
--- a/src/Compiler/xlf/FSComp.txt.ru.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ru.xlf
@@ -92,11 +92,6 @@
         Использование "incr" из библиотеки F# является нерекомендуемым. См. https://aka.ms/fsharp-refcell-ops. Например, замените "incr cell" на "cell.Value <- cell.Value + 1".
         
       
-      
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        
-      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Если тип использует оба атрибута [<Sealed>] и [<AbstractClass>], это означает, что он статический. Привязки экземпляра let не разрешены.
@@ -178,13 +173,13 @@
         
       
       
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
         
       
       
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
         
       
       
@@ -1002,11 +997,6 @@
         Атрибуты не могут быть применены к расширениям типа.
         
       
-      
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        
-      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Это выражение записи копирования и обновления изменяет все поля типа записи "{0}". Вместо этого можно использовать синтаксис конструкции записи.
diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf
index 4d8e47af9a0..e598d1e70d8 100644
--- a/src/Compiler/xlf/FSComp.txt.tr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.tr.xlf
@@ -92,11 +92,6 @@
         F# kitaplığından gelen 'incr' kullanımı kullanım dışı. https://aka.ms/fsharp-refcell-ops’a bakın. Örneğin, lütfen 'incr cell' ifadesini 'cell.Value <- cell.Value + 1' olarak değiştirin.
         
       
-      
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        
-      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         Bir tür, hem [<Sealed>] hem de [< AbstractClass>] özniteliklerini kullanıyorsa bu statik olduğu anlamına gelir. Örnek let bağlamalarına izin verilmez.
@@ -178,13 +173,13 @@
         
       
       
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
         
       
       
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
         
       
       
@@ -1002,11 +997,6 @@
         Öznitelikler tür uzantılarına uygulanamaz.
         
       
-      
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        
-      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         Bu kopyalama ve güncelleştirme kayıt ifadesi, '{0}' kayıt türündeki tüm alanları değiştirir. Bunun yerine kayıt oluşturma söz dizimini kullanmayı deneyin.
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
index 6a537df75ee..2ea8e974fae 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
@@ -92,11 +92,6 @@
         已弃用 F# 库中的“incr”。请参阅 https://aka.ms/fsharp-refcell-ops。 例如,请将“incr cell”更改为“cell.Value <- cell.Value + 1”。
         
       
-      
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        
-      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         如果类型同时使用 [<Sealed>] 和 [<AbstractClass>] 属性,则表示它是静态的。不允许使用实例允许绑定。
@@ -178,13 +173,13 @@
         
       
       
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
         
       
       
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
         
       
       
@@ -1002,11 +997,6 @@
         属性不可应用于类型扩展。
         
       
-      
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        
-      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         此复制和更新记录表达式更改记录类型“{0}”的所有字段。请考虑改用记录构造语法。
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
index 7fd1a1098fe..9b4ee91cb0d 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
@@ -92,11 +92,6 @@
         透過 F# 程式庫使用 'incr' 的方式已淘汰。請參閱 https://aka.ms/fsharp-refcell-ops。舉例來說,請將 'incr cell' 變更為 'cell.Value <- cell.Value + 1'。
         
       
-      
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        Nullness warning. The 'DefaultValue' attribute is used but the type (or one of its fields if a struct) is non-nullable.
-        
-      
       
         If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Instance let bindings are not allowed.
         如果類型同時使用 [<Sealed>] 和 [<AbstractClass>] 屬性,表示其為靜態。不允許執行個體 'let' 繫結。
@@ -178,13 +173,13 @@
         
       
       
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
-        The type '{0}' has 'null' as an extra value but a constraint does not permit this
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
         
       
       
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
-        The type '{0}' has 'null' as a true representation value but a constraint does not permit this
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
         
       
       
@@ -1002,11 +997,6 @@
         屬性無法套用到類型延伸模組。
         
       
-      
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        Nullness warning. The default constructor of a struct type is required but one of the fields of struct type is non-nullable.
-        
-      
       
         This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead.
         此複製和更新記錄運算式將變更記錄類型為 '{0}' 的所有欄位。請考慮改用記錄建構語法。
diff --git a/src/Compiler/xlf/FSStrings.cs.xlf b/src/Compiler/xlf/FSStrings.cs.xlf
index 3b399e8d46e..9243bbb1e99 100644
--- a/src/Compiler/xlf/FSStrings.cs.xlf
+++ b/src/Compiler/xlf/FSStrings.cs.xlf
@@ -2,24 +2,24 @@
 
   
     
-      
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
         
       
       
-        Nullness warning: The type '{0}' does not support nullness.
-        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
         
       
       
diff --git a/src/Compiler/xlf/FSStrings.de.xlf b/src/Compiler/xlf/FSStrings.de.xlf
index bd68a3675e3..20cd1c86b48 100644
--- a/src/Compiler/xlf/FSStrings.de.xlf
+++ b/src/Compiler/xlf/FSStrings.de.xlf
@@ -2,24 +2,24 @@
 
   
     
-      
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
         
       
       
-        Nullness warning: The type '{0}' does not support nullness.
-        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
         
       
       
diff --git a/src/Compiler/xlf/FSStrings.es.xlf b/src/Compiler/xlf/FSStrings.es.xlf
index 2470385a990..8090f7b2152 100644
--- a/src/Compiler/xlf/FSStrings.es.xlf
+++ b/src/Compiler/xlf/FSStrings.es.xlf
@@ -2,24 +2,24 @@
 
   
     
-      
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
         
       
       
-        Nullness warning: The type '{0}' does not support nullness.
-        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
         
       
       
diff --git a/src/Compiler/xlf/FSStrings.fr.xlf b/src/Compiler/xlf/FSStrings.fr.xlf
index ddc17e5c270..ea985ab025e 100644
--- a/src/Compiler/xlf/FSStrings.fr.xlf
+++ b/src/Compiler/xlf/FSStrings.fr.xlf
@@ -2,24 +2,24 @@
 
   
     
-      
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
         
       
       
-        Nullness warning: The type '{0}' does not support nullness.
-        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
         
       
       
diff --git a/src/Compiler/xlf/FSStrings.it.xlf b/src/Compiler/xlf/FSStrings.it.xlf
index e4845cfd12b..94a1fff93bc 100644
--- a/src/Compiler/xlf/FSStrings.it.xlf
+++ b/src/Compiler/xlf/FSStrings.it.xlf
@@ -2,24 +2,24 @@
 
   
     
-      
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
         
       
       
-        Nullness warning: The type '{0}' does not support nullness.
-        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
         
       
       
diff --git a/src/Compiler/xlf/FSStrings.ja.xlf b/src/Compiler/xlf/FSStrings.ja.xlf
index 5f49b8eb56b..cffa76300ac 100644
--- a/src/Compiler/xlf/FSStrings.ja.xlf
+++ b/src/Compiler/xlf/FSStrings.ja.xlf
@@ -2,24 +2,24 @@
 
   
     
-      
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
         
       
       
-        Nullness warning: The type '{0}' does not support nullness.
-        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
         
       
       
diff --git a/src/Compiler/xlf/FSStrings.ko.xlf b/src/Compiler/xlf/FSStrings.ko.xlf
index 54a71c5fe12..83b47b3df4f 100644
--- a/src/Compiler/xlf/FSStrings.ko.xlf
+++ b/src/Compiler/xlf/FSStrings.ko.xlf
@@ -2,24 +2,24 @@
 
   
     
-      
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
         
       
       
-        Nullness warning: The type '{0}' does not support nullness.
-        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
         
       
       
diff --git a/src/Compiler/xlf/FSStrings.pl.xlf b/src/Compiler/xlf/FSStrings.pl.xlf
index 6845eae60ce..36829f79504 100644
--- a/src/Compiler/xlf/FSStrings.pl.xlf
+++ b/src/Compiler/xlf/FSStrings.pl.xlf
@@ -2,24 +2,24 @@
 
   
     
-      
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
         
       
       
-        Nullness warning: The type '{0}' does not support nullness.
-        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
         
       
       
diff --git a/src/Compiler/xlf/FSStrings.pt-BR.xlf b/src/Compiler/xlf/FSStrings.pt-BR.xlf
index f31a0882f77..ce3337d3777 100644
--- a/src/Compiler/xlf/FSStrings.pt-BR.xlf
+++ b/src/Compiler/xlf/FSStrings.pt-BR.xlf
@@ -2,24 +2,24 @@
 
   
     
-      
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
         
       
       
-        Nullness warning: The type '{0}' does not support nullness.
-        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
         
       
       
diff --git a/src/Compiler/xlf/FSStrings.ru.xlf b/src/Compiler/xlf/FSStrings.ru.xlf
index 54fb0c052fd..2f8c7a32041 100644
--- a/src/Compiler/xlf/FSStrings.ru.xlf
+++ b/src/Compiler/xlf/FSStrings.ru.xlf
@@ -2,24 +2,24 @@
 
   
     
-      
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
         
       
       
-        Nullness warning: The type '{0}' does not support nullness.
-        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
         
       
       
diff --git a/src/Compiler/xlf/FSStrings.tr.xlf b/src/Compiler/xlf/FSStrings.tr.xlf
index 43d48a8ea73..91baa073a99 100644
--- a/src/Compiler/xlf/FSStrings.tr.xlf
+++ b/src/Compiler/xlf/FSStrings.tr.xlf
@@ -2,24 +2,24 @@
 
   
     
-      
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
         
       
       
-        Nullness warning: The type '{0}' does not support nullness.
-        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
         
       
       
diff --git a/src/Compiler/xlf/FSStrings.zh-Hans.xlf b/src/Compiler/xlf/FSStrings.zh-Hans.xlf
index 4bd02158e64..66bd6b6d79d 100644
--- a/src/Compiler/xlf/FSStrings.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSStrings.zh-Hans.xlf
@@ -2,24 +2,24 @@
 
   
     
-      
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
         
       
       
-        Nullness warning: The type '{0}' does not support nullness.
-        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
         
       
       
diff --git a/src/Compiler/xlf/FSStrings.zh-Hant.xlf b/src/Compiler/xlf/FSStrings.zh-Hant.xlf
index ba3f25a9471..d68f93077e8 100644
--- a/src/Compiler/xlf/FSStrings.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSStrings.zh-Hant.xlf
@@ -2,24 +2,24 @@
 
   
     
-      
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
-        Nullness warning: The type '{0}' supports a null value but a constraint requires the type to be non-null.
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
         
       
       
-        Nullness warning: The type '{0}' does not support nullness.
-        Nullness warning: The type '{0}' does not support nullness.
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
         
       
       
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
-        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability '{2}' and '{3}'.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
         
       
       
diff --git a/src/FSharp.Core/seqcore.fs b/src/FSharp.Core/seqcore.fs
index d5426d4ffe0..4dd050f1249 100644
--- a/src/FSharp.Core/seqcore.fs
+++ b/src/FSharp.Core/seqcore.fs
@@ -169,7 +169,7 @@ module internal IEnumerator =
                       f()
         }
 
-    let inline checkNonNull argName arg =
+    let inline checkNonNull argName (arg: 'T when 'T : null) =
         if isNull arg then
             nullArg argName
 
diff --git a/tests/adhoc/nullness/enabled/negative.fs b/tests/adhoc/nullness/enabled/negative.fs
index 6982a8baf5e..d3509f2ab1d 100644
--- a/tests/adhoc/nullness/enabled/negative.fs
+++ b/tests/adhoc/nullness/enabled/negative.fs
@@ -3,3 +3,54 @@ open System
 module Basics2 = 
     let f6 () : 'T __withnull when 'T : not struct and 'T : null = null // Expected to give an error about inconistent constraints
 
+module NullConstraintTests =
+    type C<'T when 'T : null>() = class end
+
+    let f1 (y : C< (int * int) >) = y // This gave an error in previous F# and we expect it to continue to give an error
+
+    let f2 (y : C>) = y // This gave an error in previous F# and we expect it to continue to give an error
+
+    let f7 (y : C> __withnull) = y // We expect this to give an error
+
+    module StructExamples = 
+
+        []
+        type C1 =
+            []
+            val mutable Whoops : String // expect a warning
+
+        []
+        type C4a =
+            []
+            val mutable Whoops : int FSharp.Collections.List // expect a hard error like in previous F#
+
+        []
+        type C5 =
+            []
+            val mutable Whoops : int * int // expect an error like previous F#
+
+        []
+        type C6 =
+            []
+            val mutable Whoops : int -> int // expect an error like previous F#
+
+    module ClassExamples = 
+        type C1 =
+            []
+            val mutable Whoops : String // expect an error if checknulls is on
+
+        type C4a =
+            []
+            val mutable Whoops : int FSharp.Collections.List // expect an error if checknulls is on
+
+        type C5 =
+            []
+            val mutable Whoops : int * int // expect an error like previous F#
+
+        type C6 =
+            []
+            val mutable Whoops : int -> int // expect an error like previous F#
+
+        type C7 =
+            []
+            val mutable Whoops : (int -> int) __withnull // expect no warning
diff --git a/tests/adhoc/nullness/enabled/positive.fs b/tests/adhoc/nullness/enabled/positive.fs
index 44b43ea9ea9..76428ce8355 100644
--- a/tests/adhoc/nullness/enabled/positive.fs
+++ b/tests/adhoc/nullness/enabled/positive.fs
@@ -1,5 +1,5 @@
+module EnabledPositive
 open System
-
 module Basics =     
     let x2 : String __withnull = null // expect no warning in any configuration
     let x3 : String __withnull = "a"  // expect no warning in any configuration
@@ -48,7 +48,7 @@ type C(s: String) =
 
 
 // This give a warning since 'T is not known to be reference type non-null
-let f<'T> (x: 'T __withnull, y: 'T __withnull) = ()
+let f<'T when 'T: __notnull > (x: 'T __withnull, y: 'T __withnull) = ()
 
 module Extractions0c =
 
@@ -186,11 +186,6 @@ let f0 line =
 module NullConstraintTests =
     type C<'T when 'T : null>() = class end
 
-    let f1 (y : C< (int * int) >) = y // This gave an error in previous F# and we expect it to continue to give an error
-
-    // This gave an error in previous F#.
-    let f2 (y : C) = y
-
     let f3 (y : C) = y // Expect a Nullness warning
 
     let f4 (y : C) = y // No warning expected 
@@ -199,18 +194,10 @@ module NullConstraintTests =
 
     let f6 (y : C __withnull>) = y // No warning expected, lexing/parsing should succeed 
 
-    let f7 (y : C> __withnull) = y // No warning expected, lexing/parsing should succeed
-
-
 module DefaultValueTests =
 
 
     module StructExamples = 
-        []
-        type C1 =
-            []
-            val mutable Whoops : String // expect a warning
-
         []
         type C2 =
             []
@@ -221,25 +208,10 @@ module DefaultValueTests =
             []
             val mutable Whoops : String __withnull // expect no warning
 
-        []
-        type C4a =
-            []
-            val mutable Whoops : int FSharp.Collections.List // expect a hard error like in previous F#
-
         []
         type C4b =
             []
-            val mutable Whoops : int FSharp.Collections.List __withnull // expect no warning
-
-        []
-        type C5 =
-            []
-            val mutable Whoops : int * int // expect an error like previous F#
-
-        []
-        type C6 =
-            []
-            val mutable Whoops : int -> int // expect an error like previous F#
+            val mutable Whoops : FSharp.Collections.List __withnull // expect no warning
 
         []
         type C7 =
@@ -247,9 +219,6 @@ module DefaultValueTests =
             val mutable Whoops : (int -> int) __withnull // expect no warning
 
     module ClassExamples = 
-        type C1 =
-            []
-            val mutable Whoops : String // expect a warning
 
         type C2 =
             []
@@ -259,22 +228,10 @@ module DefaultValueTests =
             []
             val mutable Whoops : String __withnull // expect no warning
 
-        type C4a =
-            []
-            val mutable Whoops : int FSharp.Collections.List // ** expect a warning
-
         type C4b =
             []
             val mutable Whoops : int FSharp.Collections.List __withnull // expect no warning
 
-        type C5 =
-            []
-            val mutable Whoops : int * int // expect an error like previous F#
-
-        type C6 =
-            []
-            val mutable Whoops : int -> int // expect an error like previous F#
-
         type C7 =
             []
             val mutable Whoops : (int -> int) __withnull // expect no warning
diff --git a/tests/adhoc/nullness/enabled/positive.next.bsl b/tests/adhoc/nullness/enabled/positive.next.bsl
index 8aa67c5962e..133a186a32e 100644
--- a/tests/adhoc/nullness/enabled/positive.next.bsl
+++ b/tests/adhoc/nullness/enabled/positive.next.bsl
@@ -1,16 +1,12 @@
 
 tests\adhoc\nullness\enabled\positive.fs(8,24): warning FS3271: The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
 
+tests\adhoc\nullness\enabled\positive.fs(51,15): warning FS3271: The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+
 tests\adhoc\nullness\enabled\positive.fs(56,19): warning FS3271: The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
 
 tests\adhoc\nullness\enabled\positive.fs(63,19): warning FS3271: The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
 
-tests\adhoc\nullness\enabled\positive.fs(208,17): error FS0001: The type '(int * int)' does not have 'null' as a proper value
-
-tests\adhoc\nullness\enabled\positive.fs(214,17): error FS0001: The type 'int list' does not have 'null' as a proper value
-
-tests\adhoc\nullness\enabled\positive.fs(220,17): error FS0001: The type 'int list' does not have 'null' as a proper value
-
-tests\adhoc\nullness\enabled\positive.fs(222,17): error FS0001: The type 'String list' does not have 'null' as a proper value
+tests\adhoc\nullness\enabled\positive.fs(193,17): error FS0001: The type 'List' does not have 'null' as a proper value
 
-tests\adhoc\nullness\enabled\positive.fs(224,17): error FS0001: The type 'String list' does not have 'null' as a proper value
+tests\adhoc\nullness\enabled\positive.fs(195,17): error FS0001: The type 'List' does not have 'null' as a proper value
diff --git a/tests/adhoc/nullness/enabled/positive.next.enabled.bsl b/tests/adhoc/nullness/enabled/positive.next.enabled.bsl
index ac6614cea16..a63c8033adc 100644
--- a/tests/adhoc/nullness/enabled/positive.next.enabled.bsl
+++ b/tests/adhoc/nullness/enabled/positive.next.enabled.bsl
@@ -3,16 +3,6 @@ tests\adhoc\nullness\enabled\positive.fs(13,18): warning FS3261: Nullness warnin
 
 tests\adhoc\nullness\enabled\positive.fs(19,26): warning FS3261: Nullness warning: The type 'int option' uses 'null' as a representation value but a non-null type is expected.
 
-tests\adhoc\nullness\enabled\positive.fs(51,15): error FS0043: A type parameter is missing a constraint 'when 'T: __notnull'
+tests\adhoc\nullness\enabled\positive.fs(214,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
 
-tests\adhoc\nullness\enabled\positive.fs(51,33): error FS0043: A type parameter is missing a constraint 'when 'T: __notnull'
-
-tests\adhoc\nullness\enabled\positive.fs(208,17): error FS0001: The type '(int * int)' does not have 'null' as a proper value
-
-tests\adhoc\nullness\enabled\positive.fs(214,17): error FS0001: The type 'int list' does not have 'null' as a proper value
-
-tests\adhoc\nullness\enabled\positive.fs(220,17): error FS0001: The type 'int list __withnull' does not have 'null' as a proper value
-
-tests\adhoc\nullness\enabled\positive.fs(222,17): error FS0001: The type 'String list __withnull' does not have 'null' as a proper value
-
-tests\adhoc\nullness\enabled\positive.fs(224,17): error FS0001: The type 'String list' does not have 'null' as a proper value
+tests\adhoc\nullness\enabled\positive.fs(219,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
diff --git a/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl b/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl
index eb4c0a63735..f5ea0050726 100644
--- a/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl
+++ b/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl
@@ -21,50 +21,40 @@ tests\adhoc\nullness\enabled\positive.fs(29,14): warning FS3261: Nullness warnin
 
 tests\adhoc\nullness\enabled\positive.fs(43,26): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
 
-tests\adhoc\nullness\enabled\positive.fs(51,15): error FS0043: A type parameter is missing a constraint 'when 'T: __notnull'
+tests\adhoc\nullness\enabled\positive.fs(85,67): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(51,33): error FS0043: A type parameter is missing a constraint 'when 'T: __notnull'
+tests\adhoc\nullness\enabled\positive.fs(85,67): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(88,67): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(86,89): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(88,67): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(86,89): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(89,89): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(86,100): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(89,89): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(86,100): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(89,100): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(91,57): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(89,100): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(91,57): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(94,57): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(92,80): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(94,57): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(92,80): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(95,80): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(92,91): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(95,80): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(92,91): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(95,91): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(120,32): warning FS3261: Nullness warning: The type 'obj array' is non-null, but a type supporting 'null' is expected.
 
-tests\adhoc\nullness\enabled\positive.fs(95,91): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(129,4): warning FS3261: Nullness warning: A non-null type is expected. The types 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' and 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(123,32): warning FS3261: Nullness warning: The type 'obj array' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\enabled\positive.fs(134,5): warning FS3261: Nullness warning: A non-null type is expected. The types 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' and 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(132,4): warning FS3261: Nullness warning: A non-null type is expected. The types 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' and 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(159,36): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
 
-tests\adhoc\nullness\enabled\positive.fs(137,5): warning FS3261: Nullness warning: A non-null type is expected. The types 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' and 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(162,41): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
 
-tests\adhoc\nullness\enabled\positive.fs(162,36): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\enabled\positive.fs(164,37): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
 
-tests\adhoc\nullness\enabled\positive.fs(165,41): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
-
-tests\adhoc\nullness\enabled\positive.fs(167,37): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
-
-tests\adhoc\nullness\enabled\positive.fs(208,17): warning FS3261: Nullness warning: The type '(int * int)' is non-null, but a type supporting 'null' is expected.
-
-tests\adhoc\nullness\enabled\positive.fs(211,17): warning FS3261: Nullness warning: The type 'List' is non-null, but a type supporting 'null' is expected.
-
-tests\adhoc\nullness\enabled\positive.fs(213,17): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
-
-tests\adhoc\nullness\enabled\positive.fs(221,17): warning FS3261: Nullness warning: The type 'List' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\enabled\positive.fs(189,17): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
diff --git a/tests/adhoc/nullness/existing/negative.fs b/tests/adhoc/nullness/existing/negative.fs
index 1291546a2d9..42994095622 100644
--- a/tests/adhoc/nullness/existing/negative.fs
+++ b/tests/adhoc/nullness/existing/negative.fs
@@ -9,9 +9,16 @@ module NullConstraintTests =
 
     let f2 (y : C) = y // This gave an error in F# 4.5 and we expect it to continue to give an error
 
+    let f3 (y : C int>) = y // This gave an error in F# 4.5 and we expect it to continue to give an error
+
 module DefaultValueTests =
 
     module StructExamples = 
+        []
+        type C1 =
+            []
+            val mutable Whoops : String // expect an error if checknulls is on
+
         []
         type C4a =
             []
@@ -31,77 +38,13 @@ module DefaultValueTests =
 
         type C4a =
             []
-            val mutable Whoops : int list // should have given an error in F# 4.5 but didn't
+            val mutable Whoops : int list // Should have given an error in F# 4.5 but didn't. Expect a corrective error if checknulls is on
 
         type C5 =
             []
-            val mutable Whoops : int * int // should have given an error in F# 4.5 but didn't
+            val mutable Whoops : int * int // Should have given an error in F# 4.5 but didn't. Expect a corrective error if checknulls is on
 
         type C6 =
             []
-            val mutable Whoops : int -> int // should have given an error in F# 4.5 but didn't
-
-
-#if LIBRARY_SUPPORT
-module Library =     
-
-    let x5 = nonNull "" // Should not give a Nullness warning
-    check "ekjnceoiwe5" x5 ""
-    let x6 = nonNull "" // **Expected to give a Nullness warning, expected also to give a warning with nullness checking off
-    check "ekjnceoiwe6" x6 ""
-    let x7 = nonNull ""
-    check "ekjnceoiwe7" x7 ""
-    let _x7 : string = x7
-    let x8 = nonNull Array.empty
-    check "ekjnceoiwe8" x8 [| |]
-    let x9 = nonNull [| "" |]
-    check "ekjnceoiwe9" x9 [| "" |]
-    let x10 = nonNullV (Nullable(3))
-    check "ekjnceoiwe10" x10 3
-    let x11 = try nonNullV (Nullable()) with :? System.NullReferenceException -> 10
-    check "ekjnceoiwe11" x11 10
-    let x12 = nullV
-    check "ekjnceoiwe12" x12 (Nullable())
-    let x13 = nullV
-    check "ekjnceoiwe13" x13 (Nullable())
-    let x14 = withNullV 6L
-    check "ekjnceoiwe14" x14 (Nullable(6L))
-    let x15 : string __withnull = withNull x4
-    check "ekjnceoiwe15" x15 ""
-    let x15a : string __withnull = withNull ""
-    check "ekjnceoiwe15a" x15a ""
-    let x15b : string __withnull = withNull x4
-    check "ekjnceoiwe15b" x15b ""
-    let x15c : string __withnull = withNull x4 // **Expected to give a Nullness warning
-    check "ekjnceoiwe15c" x15c ""
-    let x16 : Nullable = withNullV 3
-    check "ekjnceoiwe16" x16 (Nullable(3))
-    
-    let y0 = isNull null // Should not give a Nullness warning (obj)
-    check "ekjnceoiwey0" y0 true
-    let y1 = isNull (null: obj __withnull) // Should not give a Nullness warning
-    check "ekjnceoiwey1" y1 true
-    let y1b = isNull (null: string __withnull) // Should not give a Nullness warning
-    check "ekjnceoiwey1b" y1b true
-    let y2 = isNull "" // **Expected to give a Nullness warning - type instantiation of a nullable type is non-nullable string
-    check "ekjnceoiwey2" y2 false
-    let y9 = isNull "" // **Expected to give a Nullness warning - type instantiation of a nullable type is non-nullable string
-    check "ekjnceoiwey9" y9 false
-    let y10 = isNull "" // Should not give a Nullness warning.
-    check "ekjnceoiwey10" y10 false
-    // Not yet allowed 
-    //let f7 () : 'T __withnull when 'T : struct = null
-    let f7b () : Nullable<'T> = nullV // BUG: Incorrectly gives a warning about System.ValueType with /test:AssumeNullOnImport
-
-    let f0b line = 
-        let add (s:string) = ()
-        match line with 
-        | null  -> ()
-        | _ -> add (nonNull line) // Exected to give a nullness warning
-
-    let add (s:string) = ()
-    let f0c line = 
-        add (nonNull "") // WRONG: should not give a nullness warning
-
+            val mutable Whoops : int -> int // Should have given an error in F# 4.5 but didn't. Expect a corrective error if checknulls is on
 
-#endif
diff --git a/tests/adhoc/nullness/existing/negative.next.bsl b/tests/adhoc/nullness/existing/negative.next.bsl
index c1f4ac01b13..9cb7a4b46e4 100644
--- a/tests/adhoc/nullness/existing/negative.next.bsl
+++ b/tests/adhoc/nullness/existing/negative.next.bsl
@@ -2,3 +2,5 @@
 tests\adhoc\nullness\existing\negative.fs(8,17): error FS0001: The type '(int * int)' does not have 'null' as a proper value
 
 tests\adhoc\nullness\existing\negative.fs(10,17): error FS0001: The type 'int list' does not have 'null' as a proper value
+
+tests\adhoc\nullness\existing\negative.fs(12,17): error FS0001: The type '(int -> int)' does not have 'null' as a proper value
diff --git a/tests/adhoc/nullness/existing/negative.next.enabled.bsl b/tests/adhoc/nullness/existing/negative.next.enabled.bsl
index c1f4ac01b13..9cb7a4b46e4 100644
--- a/tests/adhoc/nullness/existing/negative.next.enabled.bsl
+++ b/tests/adhoc/nullness/existing/negative.next.enabled.bsl
@@ -2,3 +2,5 @@
 tests\adhoc\nullness\existing\negative.fs(8,17): error FS0001: The type '(int * int)' does not have 'null' as a proper value
 
 tests\adhoc\nullness\existing\negative.fs(10,17): error FS0001: The type 'int list' does not have 'null' as a proper value
+
+tests\adhoc\nullness\existing\negative.fs(12,17): error FS0001: The type '(int -> int)' does not have 'null' as a proper value
diff --git a/tests/adhoc/nullness/existing/negative.next.enabled.checknulls.bsl b/tests/adhoc/nullness/existing/negative.next.enabled.checknulls.bsl
index ea1aad9ff41..ca1be2e32fc 100644
--- a/tests/adhoc/nullness/existing/negative.next.enabled.checknulls.bsl
+++ b/tests/adhoc/nullness/existing/negative.next.enabled.checknulls.bsl
@@ -1,14 +1,18 @@
 
 tests\adhoc\nullness\existing\negative.fs(8,17): warning FS3261: Nullness warning: The type '(int * int)' is non-null, but a type supporting 'null' is expected.
 
-tests\adhoc\nullness\existing\negative.fs(18,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+tests\adhoc\nullness\existing\negative.fs(12,17): warning FS3261: Nullness warning: The type '(int -> int)' is non-null, but a type supporting 'null' is expected.
 
-tests\adhoc\nullness\existing\negative.fs(23,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+tests\adhoc\nullness\existing\negative.fs(20,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
 
-tests\adhoc\nullness\existing\negative.fs(28,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+tests\adhoc\nullness\existing\negative.fs(25,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
 
-tests\adhoc\nullness\existing\negative.fs(34,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+tests\adhoc\nullness\existing\negative.fs(30,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
 
-tests\adhoc\nullness\existing\negative.fs(38,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+tests\adhoc\nullness\existing\negative.fs(35,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
 
-tests\adhoc\nullness\existing\negative.fs(42,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+tests\adhoc\nullness\existing\negative.fs(41,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+
+tests\adhoc\nullness\existing\negative.fs(45,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+
+tests\adhoc\nullness\existing\negative.fs(49,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
diff --git a/tests/adhoc/nullness/existing/negative.previous.bsl b/tests/adhoc/nullness/existing/negative.previous.bsl
index c1f4ac01b13..9cb7a4b46e4 100644
--- a/tests/adhoc/nullness/existing/negative.previous.bsl
+++ b/tests/adhoc/nullness/existing/negative.previous.bsl
@@ -2,3 +2,5 @@
 tests\adhoc\nullness\existing\negative.fs(8,17): error FS0001: The type '(int * int)' does not have 'null' as a proper value
 
 tests\adhoc\nullness\existing\negative.fs(10,17): error FS0001: The type 'int list' does not have 'null' as a proper value
+
+tests\adhoc\nullness\existing\negative.fs(12,17): error FS0001: The type '(int -> int)' does not have 'null' as a proper value
diff --git a/tests/adhoc/nullness/existing/positive.fs b/tests/adhoc/nullness/existing/positive.fs
index 505034ad95b..a87d5dff156 100644
--- a/tests/adhoc/nullness/existing/positive.fs
+++ b/tests/adhoc/nullness/existing/positive.fs
@@ -1,3 +1,4 @@
+module ExistingPositive
 open System
 open System.Diagnostics
 open System.Runtime.CompilerServices
@@ -56,10 +57,6 @@ module NullConstraintTests =
 module DefaultValueTests =
 
     module StructExamples = 
-        []
-        type C1 =
-            []
-            val mutable Whoops : String // expect an error if checknulls is on
 
         []
         type C2 =
@@ -67,23 +64,6 @@ module DefaultValueTests =
             val mutable Whoops : String // expect no warning or error under any configuration
 
     module ClassExamples = 
-        type C1 =
-            []
-            val mutable Whoops : String // expect an error if checknulls is on
-
         type C2 =
             []
             val mutable Whoops : String // expect no warning or error under any configuration
-
-        type C4a =
-            []
-            val mutable Whoops : int list // should have given an error in F# 4.5 but didn't, we expect a corrective error if checknulls is on
-
-        type C5 =
-            []
-            val mutable Whoops : int * int // should have given an error in F# 4.5 but didn't, we expect a corrective error if checknulls is on
-
-        type C6 =
-            []
-            val mutable Whoops : int -> int // should have given an error in F# 4.5 but didn't, we expect a corrective error if checknulls is on
-
diff --git a/tests/adhoc/nullness/existing/positive.next.enabled.checknulls.bsl b/tests/adhoc/nullness/existing/positive.next.enabled.checknulls.bsl
index 812c4ba829c..c83ee6b5bc2 100644
--- a/tests/adhoc/nullness/existing/positive.next.enabled.checknulls.bsl
+++ b/tests/adhoc/nullness/existing/positive.next.enabled.checknulls.bsl
@@ -1,18 +1,8 @@
 
-tests\adhoc\nullness\existing\positive.fs(23,23): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\existing\positive.fs(24,23): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
 
-tests\adhoc\nullness\existing\positive.fs(28,26): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\existing\positive.fs(29,26): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
 
-tests\adhoc\nullness\existing\positive.fs(43,32): warning FS3261: Nullness warning: The type 'obj array' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\existing\positive.fs(44,32): warning FS3261: Nullness warning: The type 'obj array' is non-null, but a type supporting 'null' is expected.
 
-tests\adhoc\nullness\existing\positive.fs(54,17): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
-
-tests\adhoc\nullness\existing\positive.fs(62,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
-
-tests\adhoc\nullness\existing\positive.fs(72,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
-
-tests\adhoc\nullness\existing\positive.fs(80,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
-
-tests\adhoc\nullness\existing\positive.fs(84,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
-
-tests\adhoc\nullness\existing\positive.fs(88,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+tests\adhoc\nullness\existing\positive.fs(55,17): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
diff --git a/tests/adhoc/nullness/nullness.fsproj b/tests/adhoc/nullness/nullness.fsproj
index 95d78a3acc1..bf8b0eaaaf8 100644
--- a/tests/adhoc/nullness/nullness.fsproj
+++ b/tests/adhoc/nullness/nullness.fsproj
@@ -9,14 +9,14 @@
     
 	$(OtherFlags) --nowarn:57
 	$(OtherFlags) --langversion:preview
-
+	$(OtherFlags) /checknulls /sig:out.fsi 
   
 
   
 	
 	
 	
-  
+  
   
 
 
diff --git a/tests/adhoc/nullness/validate.cmd b/tests/adhoc/nullness/validate.cmd
index 2e3e275a9bc..9b9bd182f92 100644
--- a/tests/adhoc/nullness/validate.cmd
+++ b/tests/adhoc/nullness/validate.cmd
@@ -1,4 +1,6 @@
-dotnet build src\fsc\fscProject -f net472 -c Proto -p ProtoDebug=true
+REM devenv FSharp.sln /ProjectConfig Proto
+
+REM dotnet build src\fsc\fscProject -f net472 -c Proto -p ProtoDebug=true
 
 fsc.exe tests\adhoc\nullness\micro.fs -i
 fsc.exe tests\adhoc\nullness\micro.fsi tests\adhoc\nullness\micro.fs -i
@@ -32,4 +34,3 @@ artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\enabled\positive.fs
 
 REM -------------
 
-artifacts\bin\fsc\Proto\net472\fsc.exe tests\adhoc\nullness\test.fsx -i --langversion:preview

From d4779f6d8b9c3f43b5b3a90a36493df896db9126 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Wed, 24 May 2023 22:51:25 +0100
Subject: [PATCH 05/59] remove tests

---
 tests/fsharp/tests.fs | 24 ------------------------
 1 file changed, 24 deletions(-)

diff --git a/tests/fsharp/tests.fs b/tests/fsharp/tests.fs
index bfdb893c2dc..b6036104ba7 100644
--- a/tests/fsharp/tests.fs
+++ b/tests/fsharp/tests.fs
@@ -74,30 +74,6 @@ module CoreTests =
 
         testOkFile.CheckExists()
 
-    []
-    let nullness_no_checknulls () =
-        let cfg = testConfig "core/nullness"
-
-        use testOkFile = fileguard cfg "test.ok"
-
-        fsc cfg "%s -o:test-no-checknulls.exe -g --langversion:preview --define:NO_CHECKNULLS" cfg.fsc_flags ["test.fsx"]
-
-        exec cfg ("." ++ "test-no-checknulls.exe") ""
-
-        testOkFile.CheckExists()
-
-    []
-    let nullness_checknulls () =
-        let cfg = testConfig "core/nullness"
-
-        use testOkFile = fileguard cfg "test.ok"
-
-        fsc cfg "%s -o:test-checknulls.exe -g --checknulls --langversion:preview" cfg.fsc_flags ["test.fsx"]
-
-        exec cfg ("." ++ "test-checknulls.exe") ""
-
-        testOkFile.CheckExists()
-
     // This test stays in FsharpSuite for a later migration phases, it uses hardcoded #r to a C# compiled cslib.dll inside
     []
     let ``quotes-FSC-FSC_DEBUG`` () = singleTestBuildAndRun "core/quotes" FSC_DEBUG

From c8cedb0dd2d67f0a049166809cdaa70ea8f1b7f6 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Wed, 24 May 2023 22:52:12 +0100
Subject: [PATCH 06/59] fantomas

---
 src/Compiler/Driver/CompilerDiagnostics.fs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs
index 038ef04488c..6c6c64d4a20 100644
--- a/src/Compiler/Driver/CompilerDiagnostics.fs
+++ b/src/Compiler/Driver/CompilerDiagnostics.fs
@@ -690,8 +690,7 @@ type Exception with
 
             let t1, t2, _cxs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2
 
-            os.Append(ConstraintSolverNullnessWarningWithTypesE().Format t1 t2)
-            |> ignore
+            os.Append(ConstraintSolverNullnessWarningWithTypesE().Format t1 t2) |> ignore
 
             if m.StartLine <> m2.StartLine then
                 os.Append(SeeAlsoE().Format(stringOfRange m)) |> ignore

From 4d2d637b94ff930b5189d35c1793d90f082e0e5d Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Thu, 25 May 2023 01:56:25 +0100
Subject: [PATCH 07/59] skip fails

---
 tests/adhoc/nullness/nullness.fsproj | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/tests/adhoc/nullness/nullness.fsproj b/tests/adhoc/nullness/nullness.fsproj
index bf8b0eaaaf8..1c12b9cec98 100644
--- a/tests/adhoc/nullness/nullness.fsproj
+++ b/tests/adhoc/nullness/nullness.fsproj
@@ -5,18 +5,20 @@
     Exe
     true
     
-	$(OtherFlags) --nowarn:1204
+   $(OtherFlags) --nowarn:1204
     
-	$(OtherFlags) --nowarn:57
-	$(OtherFlags) --langversion:preview
-	$(OtherFlags) /checknulls /sig:out.fsi 
+    $(OtherFlags) --nowarn:57
+    $(OtherFlags) --langversion:preview
+    $(OtherFlags) /checknulls /sig:out.fsi 
+    
+    $(OtherFlags) --nowarn:3261
   
 
   
-	
-	
-	
-  
+    
+    
+    
+    
   
 
 

From 6bd707c7a545962bfb54e9374ac0ba0291d4b749 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Thu, 25 May 2023 11:40:39 +0100
Subject: [PATCH 08/59] fix tests

---
 tests/FSharp.Test.Utilities/ILChecker.fs | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/tests/FSharp.Test.Utilities/ILChecker.fs b/tests/FSharp.Test.Utilities/ILChecker.fs
index 58ba5e1b7fe..aa2ef6d8d16 100644
--- a/tests/FSharp.Test.Utilities/ILChecker.fs
+++ b/tests/FSharp.Test.Utilities/ILChecker.fs
@@ -62,7 +62,14 @@ module ILChecker =
             |> unifyRuntimeAssemblyName
             |> unifyImageBase
 
-        ilCode.Trim() |> stripComments |> unifyingAssemblyNames
+        let stripManagedResources (text: string) =
+            let result = Regex.Replace(text, "\.mresource public .*\r?\n{\s*}\r?\n", "", RegexOptions.Multiline)
+            result
+
+        ilCode.Trim()
+        |> stripComments
+        |> unifyingAssemblyNames
+        |> stripManagedResources
 
 
     let private generateIlFile dllFilePath ildasmArgs =
@@ -98,6 +105,7 @@ module ILChecker =
 
         let prepareLines (s: string) =
             s.Split('\n')
+                // Skip emitted managed resources
                 |> Array.map(fun e -> e.Trim('\r'))
                 |> Array.skipWhile(String.IsNullOrWhiteSpace)
                 |> Array.rev

From 2d7abe8a0e5870ab0c18001d6ef7dfd7d67b4851 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Thu, 25 May 2023 12:38:31 +0100
Subject: [PATCH 09/59] fix up test baselines for change in order in checking

---
 src/Compiler/Checking/ConstraintSolver.fs     | 29 ++++--------
 src/Compiler/FSComp.txt                       |  2 -
 src/Compiler/pars.fsy                         | 21 ++++-----
 src/Compiler/xlf/FSComp.txt.cs.xlf            | 10 ----
 src/Compiler/xlf/FSComp.txt.de.xlf            | 10 ----
 src/Compiler/xlf/FSComp.txt.es.xlf            | 10 ----
 src/Compiler/xlf/FSComp.txt.fr.xlf            | 10 ----
 src/Compiler/xlf/FSComp.txt.it.xlf            | 10 ----
 src/Compiler/xlf/FSComp.txt.ja.xlf            | 10 ----
 src/Compiler/xlf/FSComp.txt.ko.xlf            | 10 ----
 src/Compiler/xlf/FSComp.txt.pl.xlf            | 10 ----
 src/Compiler/xlf/FSComp.txt.pt-BR.xlf         | 10 ----
 src/Compiler/xlf/FSComp.txt.ru.xlf            | 10 ----
 src/Compiler/xlf/FSComp.txt.tr.xlf            | 10 ----
 src/Compiler/xlf/FSComp.txt.zh-Hans.xlf       | 10 ----
 src/Compiler/xlf/FSComp.txt.zh-Hant.xlf       | 10 ----
 .../fsc/misc/compiler_help_output.bsl         |  1 +
 .../BindingExpressions/BindingExpressions.fs  | 10 ++--
 tests/FSharp.Test.Utilities/Compiler.fs       |  9 ++--
 ...n_return_type_and_known_type_arguments.bsl | 32 ++++---------
 ...n_return_type_and_known_type_arguments.fsx |  6 +--
 tests/fsharp/typecheck/sigs/neg04.bsl         |  8 +---
 tests/fsharp/typecheck/sigs/neg119b.bsl       | 14 ++++--
 .../fsharp/typecheck/sigs/version50/neg20.bsl | 46 ++-----------------
 24 files changed, 62 insertions(+), 246 deletions(-)

diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs
index 366844c6a18..6495ef15655 100644
--- a/src/Compiler/Checking/ConstraintSolver.fs
+++ b/src/Compiler/Checking/ConstraintSolver.fs
@@ -1074,7 +1074,7 @@ and SolveTypMeetsTyparConstraints (csenv: ConstraintSolverEnv) ndeep m2 trace ty
 
 // nullness1: actual
 // nullness2: expected
-and SolveNullnessEquiv (csenv:ConstraintSolverEnv) m2 (trace: OptionalTrace) ty1 ty2 nullness1 nullness2 =
+and SolveNullnessEquiv (csenv: ConstraintSolverEnv) m2 (trace: OptionalTrace) ty1 ty2 nullness1 nullness2 =
     match nullness1, nullness2 with
     | Nullness.Variable nv1, Nullness.Variable nv2 when nv1 === nv2 -> 
         CompleteD
@@ -1095,7 +1095,7 @@ and SolveNullnessEquiv (csenv:ConstraintSolverEnv) m2 (trace: OptionalTrace) ty1
         | NullnessInfo.WithNull, NullnessInfo.WithNull -> CompleteD
         | NullnessInfo.WithoutNull, NullnessInfo.WithoutNull -> CompleteD
         // Allow expected of WithNull and actual of WithoutNull
-        // TODO NULLNESS:  this is not sound in contravariant cases etc.
+        // TODO NULLNESS:  this is not sound in contravariant cases etc. It is assuming covariance.
         | NullnessInfo.WithNull, NullnessInfo.WithoutNull -> CompleteD
         | _ -> 
             // NOTE: we never give nullness warnings for the 'obj' type
@@ -1109,7 +1109,7 @@ and SolveNullnessEquiv (csenv:ConstraintSolverEnv) m2 (trace: OptionalTrace) ty1
         
 // nullness1: target
 // nullness2: source
-and SolveNullnessSubsumesNullness (csenv:ConstraintSolverEnv) m2 (trace: OptionalTrace) ty1 ty2 nullness1 nullness2 =
+and SolveNullnessSubsumesNullness (csenv: ConstraintSolverEnv) m2 (trace: OptionalTrace) ty1 ty2 nullness1 nullness2 =
     match nullness1, nullness2 with
     | Nullness.Variable nv1, Nullness.Variable nv2 when nv1 === nv2 -> 
         CompleteD
@@ -1208,7 +1208,7 @@ and SolveAnonInfoEqualsAnonInfo (csenv: ConstraintSolverEnv) m2 (anonInfo1: Anon
 
 /// 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 = 
+and SolveTypeEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) (cxsln:(TraitConstraintInfo * TraitConstraintSln) option) ty1 ty2 = 
     let ndeep = ndeep + 1
     let aenv = csenv.EquivEnv
     let g = csenv.g
@@ -1309,7 +1309,8 @@ and SolveTypeEqualsType (csenv:ConstraintSolverEnv) ndeep m2 (trace: OptionalTra
            SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullness2
         )
 
-    | TType_app _, TType_app _ ->  localAbortD
+    | TType_app _, TType_app _ ->
+        localAbortD
 
     | TType_tuple (tupInfo1, l1), TType_tuple (tupInfo2, l2) -> 
         if evalTupInfoIsStruct tupInfo1 <> evalTupInfoIsStruct tupInfo2 then ErrorD (ConstraintSolverError(FSComp.SR.tcTupleStructMismatch(), csenv.m, m2)) else
@@ -2310,19 +2311,9 @@ and EnforceConstraintConsistency (csenv: ConstraintSolverEnv) ndeep m2 trace ret
         do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argsTy1 argsTy2
         return! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy1 retTy2
 
-    | TyparConstraint.SupportsComparison _, TyparConstraint.IsDelegate _  
-    | TyparConstraint.IsDelegate _ , TyparConstraint.SupportsComparison _ ->
-        return! ErrorD (Error(FSComp.SR.csDelegateComparisonConstraintInconsistent(), m))
-    
-    | TyparConstraint.NotSupportsNull _, TyparConstraint.SupportsNull _     
-    | TyparConstraint.SupportsNull _, TyparConstraint.NotSupportsNull _     ->
-        return! ErrorD (Error(FSComp.SR.csNullNotNullConstraintInconsistent(), m))
-    
-    | TyparConstraint.SupportsNull _, TyparConstraint.IsNonNullableStruct _     
-    | TyparConstraint.IsNonNullableStruct _, TyparConstraint.SupportsNull _    ->
-        return! ErrorD (Error(FSComp.SR.csStructNullConstraintInconsistent(), m))
-    
-    | TyparConstraint.IsNonNullableStruct _, TyparConstraint.IsReferenceType _     
+    | TyparConstraint.SupportsComparison _, TyparConstraint.IsDelegate _
+    | TyparConstraint.IsDelegate _, TyparConstraint.SupportsComparison _
+    | TyparConstraint.IsNonNullableStruct _, TyparConstraint.IsReferenceType _
     | TyparConstraint.IsReferenceType _, TyparConstraint.IsNonNullableStruct _   ->
         return! ErrorD (Error(FSComp.SR.csStructConstraintInconsistent(), m))
 
@@ -2489,7 +2480,7 @@ and AddConstraint (csenv: ConstraintSolverEnv) ndeep m2 trace tp newConstraint
 //    val x: 'a __withnull when 'a: not null
 //
 // When null checking is fully enabled, we prefer the latter. We can't always prefer it because it is a breaking change.
-and SolveTypeUseSupportsNull (csenv:ConstraintSolverEnv) ndeep m2 trace ty = trackErrors {
+and SolveTypeUseSupportsNull (csenv: ConstraintSolverEnv) ndeep m2 trace ty = trackErrors {
     let g = csenv.g
     let m = csenv.m
     let denv = csenv.DisplayEnv
diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt
index 6c136004759..de529d9d48f 100644
--- a/src/Compiler/FSComp.txt
+++ b/src/Compiler/FSComp.txt
@@ -1520,8 +1520,6 @@ notAFunctionButMaybeDeclaration,"This value is not a function and cannot be appl
 #3261 reserved for ConstraintSolverNullnessWarningWithType
 #3261 reserved for ConstraintSolverNullnessWarning
 3268,csNullNotNullConstraintInconsistent,"The constraints 'null' and 'not null' are inconsistent"
-3269,csStructNullConstraintInconsistent,"The constraints 'struct' and 'null' are inconsistent"
-3270,csDelegateComparisonConstraintInconsistent,"The constraints 'delegate' and 'comparison' are inconsistent"
 3271,tcNullnessCheckingNotEnabled,"The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored."
 csTypeHasNullAsTrueValue,"The type '%s' uses 'null' as a representation value but a non-null type is expected"
 csTypeHasNullAsExtraValue,"The type '%s' supports 'null' but a non-null type is expected"
diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy
index fb5b984c522..97fecc977ef 100644
--- a/src/Compiler/pars.fsy
+++ b/src/Compiler/pars.fsy
@@ -1547,22 +1547,21 @@ tyconDefn:
            SynTypeDefn($1, SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.None($1.Range), $1.Range), [], None, $1.Range, trivia) }
 
   | typeNameInfo opt_equals tyconDefnRhsBlock
-     { //match $2 with
-       //| Some _ -> ()
-       //| None ->
-       //     let (SynComponentInfo(_, _, _, lid, _, _, _, _)) = $1
-       //     // While the spec doesn't allow long idents here, the parser doesn't enforce this, so take one ident
-       //     let typeNameId = List.last lid
-       //     raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsEqualsMissingInTypeDefinition(typeNameId.ToString()))
+     { match $2 with
+       | Some _ -> ()
+       | None ->
+            let (SynComponentInfo(_, _, _, lid, _, _, _, _)) = $1
+            // While the spec doesn't allow long idents here, the parser doesn't enforce this, so take one ident
+            let typeNameId = List.last lid
+            raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsEqualsMissingInTypeDefinition(typeNameId.ToString()))
 
        let nameRange = rhs parseState 1
        let (tcDefRepr: SynTypeDefnRepr), mWith, members = $3 nameRange
        let declRange = unionRanges (rhs parseState 1) tcDefRepr.Range
        let mWhole = (declRange, members) ||> unionRangeWithListBy (fun (mem: SynMemberDefn) -> mem.Range)
-       let mEquals = rhs parseState 2
 
        fun leadingKeyword ->
-           let trivia: SynTypeDefnTrivia = { LeadingKeyword = leadingKeyword; EqualsRange = Some mEquals; WithKeyword = mWith }
+           let trivia: SynTypeDefnTrivia = { LeadingKeyword = leadingKeyword; EqualsRange = $2; WithKeyword = mWith }
            SynTypeDefn($1, tcDefRepr, members, None, mWhole, trivia) }
 
   | typeNameInfo tyconDefnAugmentation
@@ -2313,7 +2312,7 @@ typeConstraint:
      { SynTypeConstraint.WhereTyparIsValueType($1, lhs parseState) }
 
   | typar COLON IDENT STRUCT
-     { if $3 <> "not" then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier($3 + " (1)"))
+     { if $3 <> "not" then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier($3))
        SynTypeConstraint.WhereTyparIsReferenceType($1, lhs parseState) }
 
   | typar COLON NULL
@@ -5583,7 +5582,7 @@ appType:
 */
 
   | appType arrayTypeSuffix
-      {  SynType.Array($2, $1, lhs parseState) }
+      { SynType.Array($2, $1, lhs parseState) }
 
   | appType HIGH_PRECEDENCE_BRACK_APP arrayTypeSuffix /* only HPA for "name[]" allowed here */
       { SynType.Array($3, $1, lhs parseState) }
diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf
index 305bdfcb5ac..48a066369a2 100644
--- a/src/Compiler/xlf/FSComp.txt.cs.xlf
+++ b/src/Compiler/xlf/FSComp.txt.cs.xlf
@@ -117,11 +117,6 @@
         Dostupná přetížení:\n{0}
         
       
-      
-        The constraints 'delegate' and 'comparison' are inconsistent
-        The constraints 'delegate' and 'comparison' are inconsistent
-        
-      
       
         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.
@@ -167,11 +162,6 @@
         Argument {0} neodpovídá
         
       
-      
-        The constraints 'struct' and 'null' are inconsistent
-        The constraints 'struct' and 'null' are inconsistent
-        
-      
       
         The type '{0}' supports 'null' but a non-null type is expected
         The type '{0}' supports 'null' but a non-null type is expected
diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf
index 7bd9908e563..79df17fa58b 100644
--- a/src/Compiler/xlf/FSComp.txt.de.xlf
+++ b/src/Compiler/xlf/FSComp.txt.de.xlf
@@ -117,11 +117,6 @@
         Verfügbare Überladungen:\n{0}
         
       
-      
-        The constraints 'delegate' and 'comparison' are inconsistent
-        The constraints 'delegate' and 'comparison' are inconsistent
-        
-      
       
         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.
@@ -167,11 +162,6 @@
         Das Argument "{0}" stimmt nicht überein.
         
       
-      
-        The constraints 'struct' and 'null' are inconsistent
-        The constraints 'struct' and 'null' are inconsistent
-        
-      
       
         The type '{0}' supports 'null' but a non-null type is expected
         The type '{0}' supports 'null' but a non-null type is expected
diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf
index e8766233b1f..bbb5c0577fb 100644
--- a/src/Compiler/xlf/FSComp.txt.es.xlf
+++ b/src/Compiler/xlf/FSComp.txt.es.xlf
@@ -117,11 +117,6 @@
         Sobrecargas disponibles:\n{0}
         
       
-      
-        The constraints 'delegate' and 'comparison' are inconsistent
-        The constraints 'delegate' and 'comparison' are inconsistent
-        
-      
       
         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.
@@ -167,11 +162,6 @@
         El argumento "{0}" no coincide.
         
       
-      
-        The constraints 'struct' and 'null' are inconsistent
-        The constraints 'struct' and 'null' are inconsistent
-        
-      
       
         The type '{0}' supports 'null' but a non-null type is expected
         The type '{0}' supports 'null' but a non-null type is expected
diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf
index 72444d4229f..05f356d5e7a 100644
--- a/src/Compiler/xlf/FSComp.txt.fr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.fr.xlf
@@ -117,11 +117,6 @@
         Surcharges disponibles :\n{0}
         
       
-      
-        The constraints 'delegate' and 'comparison' are inconsistent
-        The constraints 'delegate' and 'comparison' are inconsistent
-        
-      
       
         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.
@@ -167,11 +162,6 @@
         L'argument '{0}' ne correspond pas
         
       
-      
-        The constraints 'struct' and 'null' are inconsistent
-        The constraints 'struct' and 'null' are inconsistent
-        
-      
       
         The type '{0}' supports 'null' but a non-null type is expected
         The type '{0}' supports 'null' but a non-null type is expected
diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf
index 4c25b1b6e0a..3d9d25c887b 100644
--- a/src/Compiler/xlf/FSComp.txt.it.xlf
+++ b/src/Compiler/xlf/FSComp.txt.it.xlf
@@ -117,11 +117,6 @@
         Overload disponibili:\n{0}
         
       
-      
-        The constraints 'delegate' and 'comparison' are inconsistent
-        The constraints 'delegate' and 'comparison' are inconsistent
-        
-      
       
         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.
@@ -167,11 +162,6 @@
         L'argomento '{0}' non corrisponde
         
       
-      
-        The constraints 'struct' and 'null' are inconsistent
-        The constraints 'struct' and 'null' are inconsistent
-        
-      
       
         The type '{0}' supports 'null' but a non-null type is expected
         The type '{0}' supports 'null' but a non-null type is expected
diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf
index d52c1a2973b..8e22ec12d01 100644
--- a/src/Compiler/xlf/FSComp.txt.ja.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ja.xlf
@@ -117,11 +117,6 @@
         使用可能なオーバーロード:\n{0}
         
       
-      
-        The constraints 'delegate' and 'comparison' are inconsistent
-        The constraints 'delegate' and 'comparison' are inconsistent
-        
-      
       
         A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation.
         ジェネリック コンストラクトでは、ジェネリック型パラメーターが構造体または参照型として認識されている必要があります。型の注釈の追加を検討してください。
@@ -167,11 +162,6 @@
         引数 '{0}' が一致しません
         
       
-      
-        The constraints 'struct' and 'null' are inconsistent
-        The constraints 'struct' and 'null' are inconsistent
-        
-      
       
         The type '{0}' supports 'null' but a non-null type is expected
         The type '{0}' supports 'null' but a non-null type is expected
diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf
index 8f1a1e287ef..c39e71d1212 100644
--- a/src/Compiler/xlf/FSComp.txt.ko.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ko.xlf
@@ -117,11 +117,6 @@
         사용 가능한 오버로드:\n{0}
         
       
-      
-        The constraints 'delegate' and 'comparison' are inconsistent
-        The constraints 'delegate' and 'comparison' are inconsistent
-        
-      
       
         A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation.
         제네릭 구문을 사용하려면 구조체 또는 참조 형식의 제네릭 형식 매개 변수가 필요합니다. 형식 주석을 추가하세요.
@@ -167,11 +162,6 @@
         '{0}' 인수가 일치하지 않습니다.
         
       
-      
-        The constraints 'struct' and 'null' are inconsistent
-        The constraints 'struct' and 'null' are inconsistent
-        
-      
       
         The type '{0}' supports 'null' but a non-null type is expected
         The type '{0}' supports 'null' but a non-null type is expected
diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf
index 2a16d8179bc..077e382a3f6 100644
--- a/src/Compiler/xlf/FSComp.txt.pl.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pl.xlf
@@ -117,11 +117,6 @@
         Dostępne przeciążenia:\n{0}
         
       
-      
-        The constraints 'delegate' and 'comparison' are inconsistent
-        The constraints 'delegate' and 'comparison' are inconsistent
-        
-      
       
         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.
@@ -167,11 +162,6 @@
         Argument „{0}” nie jest zgodny
         
       
-      
-        The constraints 'struct' and 'null' are inconsistent
-        The constraints 'struct' and 'null' are inconsistent
-        
-      
       
         The type '{0}' supports 'null' but a non-null type is expected
         The type '{0}' supports 'null' but a non-null type is expected
diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
index fd8ae9dd349..d3d2fc10b4d 100644
--- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
@@ -117,11 +117,6 @@
         Sobrecargas disponíveis:\n{0}
         
       
-      
-        The constraints 'delegate' and 'comparison' are inconsistent
-        The constraints 'delegate' and 'comparison' are inconsistent
-        
-      
       
         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.
@@ -167,11 +162,6 @@
         O argumento '{0}' não corresponde
         
       
-      
-        The constraints 'struct' and 'null' are inconsistent
-        The constraints 'struct' and 'null' are inconsistent
-        
-      
       
         The type '{0}' supports 'null' but a non-null type is expected
         The type '{0}' supports 'null' but a non-null type is expected
diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf
index 2308c960145..fe310bae7fc 100644
--- a/src/Compiler/xlf/FSComp.txt.ru.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ru.xlf
@@ -117,11 +117,6 @@
         Доступные перегрузки:\n{0}
         
       
-      
-        The constraints 'delegate' and 'comparison' are inconsistent
-        The constraints 'delegate' and 'comparison' are inconsistent
-        
-      
       
         A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation.
         В универсальной конструкции требуется использовать параметр универсального типа, известный как структура или ссылочный тип. Рекомендуется добавить заметку с типом.
@@ -167,11 +162,6 @@
         Аргумент "{0}" не соответствует
         
       
-      
-        The constraints 'struct' and 'null' are inconsistent
-        The constraints 'struct' and 'null' are inconsistent
-        
-      
       
         The type '{0}' supports 'null' but a non-null type is expected
         The type '{0}' supports 'null' but a non-null type is expected
diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf
index e598d1e70d8..1c79f64ebcb 100644
--- a/src/Compiler/xlf/FSComp.txt.tr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.tr.xlf
@@ -117,11 +117,6 @@
         Kullanılabilir aşırı yüklemeler:\n{0}
         
       
-      
-        The constraints 'delegate' and 'comparison' are inconsistent
-        The constraints 'delegate' and 'comparison' are inconsistent
-        
-      
       
         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.
@@ -167,11 +162,6 @@
         '{0}' bağımsız değişkeni eşleşmiyor
         
       
-      
-        The constraints 'struct' and 'null' are inconsistent
-        The constraints 'struct' and 'null' are inconsistent
-        
-      
       
         The type '{0}' supports 'null' but a non-null type is expected
         The type '{0}' supports 'null' but a non-null type is expected
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
index 2ea8e974fae..f8ec0c19429 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
@@ -117,11 +117,6 @@
         可用重载:\n{0}
         
       
-      
-        The constraints 'delegate' and 'comparison' are inconsistent
-        The constraints 'delegate' and 'comparison' are inconsistent
-        
-      
       
         A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation.
         泛型构造要求泛型类型参数被视为结构或引用类型。请考虑添加类型注释。
@@ -167,11 +162,6 @@
         参数 "{0}" 不匹配
         
       
-      
-        The constraints 'struct' and 'null' are inconsistent
-        The constraints 'struct' and 'null' are inconsistent
-        
-      
       
         The type '{0}' supports 'null' but a non-null type is expected
         The type '{0}' supports 'null' but a non-null type is expected
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
index 9b4ee91cb0d..4344071e590 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
@@ -117,11 +117,6 @@
         可用的多載:\n{0}
         
       
-      
-        The constraints 'delegate' and 'comparison' are inconsistent
-        The constraints 'delegate' and 'comparison' are inconsistent
-        
-      
       
         A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation.
         泛型建構要求泛型型別參數必須指定為結構或參考型別。請考慮新增型別註解。
@@ -167,11 +162,6 @@
         引數 '{0}' 不相符
         
       
-      
-        The constraints 'struct' and 'null' are inconsistent
-        The constraints 'struct' and 'null' are inconsistent
-        
-      
       
         The type '{0}' supports 'null' but a non-null type is expected
         The type '{0}' supports 'null' but a non-null type is expected
diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/misc/compiler_help_output.bsl b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/misc/compiler_help_output.bsl
index 90ec39abd82..088ce274785 100644
--- a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/misc/compiler_help_output.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/misc/compiler_help_output.bsl
@@ -70,6 +70,7 @@ Copyright (c) Microsoft Corporation. All Rights Reserved.
 --warn:                               Set a warning level (0-5)
 --nowarn:                      Disable specific warning messages
 --warnon:                      Enable specific warnings that may be off by default
+--checknulls[+|-]                        Enable nullness declarations and checks
 --consolecolors[+|-]                     Output warning and error messages in color
 
 
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/BindingExpressions/BindingExpressions.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/BindingExpressions/BindingExpressions.fs
index 89b2383dd86..08a71418a10 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/BindingExpressions/BindingExpressions.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/BindingExpressions/BindingExpressions.fs
@@ -14,6 +14,12 @@ module BindingExpressions =
         |> withOptions ["--test:ErrorRanges"]
         |> compile
 
+    let verifyCompileAsExe compilation =
+        compilation
+        |> asExe
+        |> withOptions ["--test:ErrorRanges"]
+        |> compile
+
     // This test was automatically generated (moved from FSharpQA suite - Conformance/Expressions/ApplicationExpressions/BasicApplication)
     // SOURCE=AmbigLetBinding.fs	# AmbigLetBinding
     []
@@ -102,11 +108,10 @@ module BindingExpressions =
     []
     let ``in05_fs`` compilation =
         compilation
-        |> verifyCompile
+        |> verifyCompileAsExe
         |> shouldFail
         |> withDiagnostics [
             (Error 1, Line 12, Col 13, Line 12, Col 14, "The type 'int' does not match the type 'unit'")
-            (Error 1, Line 12, Col 18, Line 12, Col 24, "Type mismatch. Expecting a\n    ''a -> 'b'    \nbut given a\n    ''a -> unit'    \nThe type 'int' does not match the type 'unit'")
             (Warning 20, Line 13, Col 5, Line 13, Col 10, "The result of this expression has type 'bool' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'.")
         ]
 
@@ -119,7 +124,6 @@ module BindingExpressions =
         |> shouldFail
         |> withDiagnostics [
             (Error 1, Line 10, Col 9, Line 10, Col 10, "The type 'int' does not match the type 'unit'")
-            (Error 1, Line 10, Col 14, Line 10, Col 20, "Type mismatch. Expecting a\n    ''a -> 'b'    \nbut given a\n    ''a -> unit'    \nThe type 'int' does not match the type 'unit'")
         ]
 
     // SOURCE=MutableLocals01.fs SCFLAGS="--warnon:3180 --optimize+ --test:ErrorRanges"
diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs
index a4d59f296f7..b060a6f16ba 100644
--- a/tests/FSharp.Test.Utilities/Compiler.fs
+++ b/tests/FSharp.Test.Utilities/Compiler.fs
@@ -1448,10 +1448,11 @@ module rec Compiler =
                 let expectedContent = File.ReadAllText(path) |> normalizeNewLines
                 let actualErrors = renderToString result                
 
-                match Environment.GetEnvironmentVariable("TEST_UPDATE_BSL") with
-                | null -> ()
-                | _ when expectedContent = actualErrors -> ()
-                | _ -> File.WriteAllText(path, actualErrors)
+                //match Environment.GetEnvironmentVariable("TEST_UPDATE_BSL") with
+                //| null -> ()
+                //| _ when expectedContent = actualErrors -> ()
+                //| _ -> File.WriteAllText(path, actualErrors)
+                File.WriteAllText(path, actualErrors)
 
                 match Assert.shouldBeSameMultilineStringSets expectedContent actualErrors with
                 | None -> () 
diff --git a/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.bsl b/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.bsl
index 698171eac59..648183cdbde 100644
--- a/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.bsl
+++ b/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.bsl
@@ -1,26 +1,14 @@
 
-neg_known_return_type_and_known_type_arguments.fsx(90,24,90,28): typecheck error FS0001: No overloads match for method 'Zero'.
+neg_known_return_type_and_known_type_arguments.fsx(16,57,16,67): typecheck error FS0043: The constraints 'struct' and 'null' are inconsistent
 
-Known return type: MonoidSample
+neg_known_return_type_and_known_type_arguments.fsx(52,54,52,64): typecheck error FS0043: The constraints 'struct' and 'null' are inconsistent
 
-Known type parameters: < MonoidSample , Zero >
+neg_known_return_type_and_known_type_arguments.fsx(54,54,54,64): typecheck error FS0043: The constraints 'struct' and 'null' are inconsistent
 
-Available overloads:
- - static member Zero.Zero: 'a array * Zero -> 'a array // Argument at index 1 doesn't match
- - static member Zero.Zero: 'a list * Zero -> 'a list // Argument at index 1 doesn't match
- - static member Zero.Zero: 'a option * Zero -> 'a option // Argument at index 1 doesn't match
- - static member Zero.Zero: ('T -> ^Monoid) * Zero -> ('T -> ^Monoid) when (Zero or ^Monoid) : (static member Zero: ^Monoid * Zero -> ^Monoid) // Argument at index 1 doesn't match
- - static member Zero.Zero: Async<^a> * Zero -> Async<^a> when (Zero or ^a) : (static member Zero: ^a * Zero -> ^a) // Argument at index 1 doesn't match
- - static member Zero.Zero: Lazy<^a> * Zero -> Lazy<^a> when (Zero or ^a) : (static member Zero: ^a * Zero -> ^a) // Argument at index 1 doesn't match
- - static member Zero.Zero: Map<'a,'b> * Zero -> Map<'a,'b> when 'a: comparison // Argument at index 1 doesn't match
- - static member Zero.Zero: ResizeArray<'a> * Zero -> ResizeArray<'a> // Argument at index 1 doesn't match
- - static member Zero.Zero: Set<'a> * Zero -> Set<'a> when 'a: comparison // Argument at index 1 doesn't match
- - static member Zero.Zero: System.TimeSpan * Zero -> System.TimeSpan // Argument at index 1 doesn't match
- - static member Zero.Zero: ^t * Default1 -> ('a1 -> 'a1) when ^t: null and ^t: struct // Argument at index 1 doesn't match
- - static member Zero.Zero: ^t * Default1 -> ^t when ^t: (static member Zero: ^t) // Argument at index 1 doesn't match
- - static member Zero.Zero: ^t * Default2 -> ('a1 -> 'a1) when ^t: null and ^t: struct // Argument at index 1 doesn't match
- - static member Zero.Zero: ^t * Default2 -> ^t when (FromInt32 or ^t) : (static member FromInt32: ^t * FromInt32 -> (int32 -> ^t)) // Argument at index 1 doesn't match
- - static member Zero.Zero: ^t * Default3 -> ^t when ^t: (static member Empty: ^t) // Argument at index 1 doesn't match
- - static member Zero.Zero: seq<'a> * Zero -> seq<'a> // Argument at index 1 doesn't match
- - static member Zero.Zero: string * Zero -> string // Argument at index 1 doesn't match
- - static member Zero.Zero: unit * Zero -> unit // Argument at index 1 doesn't match
+neg_known_return_type_and_known_type_arguments.fsx(77,30,77,98): typecheck error FS0043: This expression was expected to have type
+    ''Monoid'    
+but here has type
+    ''a -> 'a'    
+
+neg_known_return_type_and_known_type_arguments.fsx(90,24,90,28): typecheck error FS0039: The value or constructor 'zero' is not defined. Maybe you want one of the following:
+   Zero
diff --git a/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.fsx b/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.fsx
index 72bfdad9c21..947735d0e84 100644
--- a/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.fsx
+++ b/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.fsx
@@ -13,7 +13,7 @@ type Plus =
     inherit Default1
     static member inline ``+`` (x: 'Plus             , y: 'Plus             ,             _mthd: Default2) = (^Plus :  (static member (<|>) : _*_ -> _) x, y) : ^Plus
     static member inline ``+`` (x: 'Plus             , y: 'Plus             , []_mthd: Default1) = x + y : ^Plus
-
+    static member inline ``+`` (_: ^t when ^t: null and ^t: struct, _: ^t   , []_mthd: Default1) = id
     
     static member inline Invoke (x: 'Plus) (y: 'Plus) : 'Plus =
         let inline call (mthd : ^M, input1 : ^I, input2 : ^I) = ((^M or ^I) : (static member ``+`` : _*_*_ -> _) input1, input2, mthd)
@@ -49,9 +49,9 @@ type Zero =
   inherit Default1
   static member inline Zero (_: 't                             , _: Default3) = (^t : (static member Empty : ^t) ()) : 't
   static member inline Zero (_: 't                             , _: Default2) = FromInt32.Invoke 0             : 't
-
+  static member inline Zero (_: ^t when ^t: null and ^t: struct, _: Default2) = id
   static member inline Zero (_: 't                             , _: Default1) = LanguagePrimitives.GenericZero : 't
-
+  static member inline Zero (_: ^t when ^t: null and ^t: struct, _: Default1) = id
   static member        Zero (_: System.TimeSpan                , _: Zero    ) = System.TimeSpan ()
   static member        Zero (_: list<'a>                       , _: Zero    ) = []   :   list<'a>
   static member        Zero (_: option<'a>                     , _: Zero    ) = None : option<'a>
diff --git a/tests/fsharp/typecheck/sigs/neg04.bsl b/tests/fsharp/typecheck/sigs/neg04.bsl
index 57638b360fc..16e792c424f 100644
--- a/tests/fsharp/typecheck/sigs/neg04.bsl
+++ b/tests/fsharp/typecheck/sigs/neg04.bsl
@@ -30,7 +30,7 @@ neg04.fs(47,30,47,51): typecheck error FS0001: Type mismatch. Expecting a
     'seq<'a> -> 'n'    
 but given a
     ''o list -> 'p'    
-The type ''n list' does not match the type 'seq<'a>'
+The type ''a list' does not match the type 'seq<'b>'
 
 neg04.fs(47,49,47,51): typecheck error FS0784: This numeric literal requires that a module 'NumericLiteralN' defining functions FromZero, FromOne, FromInt32, FromInt64 and FromString be in scope
 
@@ -38,7 +38,7 @@ neg04.fs(47,30,47,51): typecheck error FS0001: Type mismatch. Expecting a
     'seq<'a> -> 'n'    
 but given a
     ''o list -> 'p'    
-The type ''n list' does not match the type 'seq<'a>'
+The type ''a list' does not match the type 'seq<'c>'
 
 neg04.fs(61,25,61,40): typecheck error FS0001: This expression was expected to have type
     'ClassType1'    
@@ -51,16 +51,12 @@ neg04.fs(70,21,70,36): typecheck error FS0064: This construct causes code to be
 
 neg04.fs(70,12,70,14): typecheck error FS0663: This type parameter has been used in a way that constrains it to always be 'c'
 
-neg04.fs(70,21,70,36): typecheck error FS0698: Invalid constraint: the type used for the constraint is sealed, which means the constraint could only be satisfied by at most one solution
-
 neg04.fs(76,19,76,26): typecheck error FS0698: Invalid constraint: the type used for the constraint is sealed, which means the constraint could only be satisfied by at most one solution
 
 neg04.fs(76,19,76,26): typecheck error FS0064: This construct causes code to be less generic than indicated by the type annotations. The type variable 'a has been constrained to be type 'd'.
 
 neg04.fs(76,10,76,12): typecheck error FS0663: This type parameter has been used in a way that constrains it to always be 'd'
 
-neg04.fs(76,19,76,26): typecheck error FS0698: Invalid constraint: the type used for the constraint is sealed, which means the constraint could only be satisfied by at most one solution
-
 neg04.fs(81,58,81,61): typecheck error FS0001: This expression was expected to have type
     'int'    
 but here has type
diff --git a/tests/fsharp/typecheck/sigs/neg119b.bsl b/tests/fsharp/typecheck/sigs/neg119b.bsl
index e5edc502670..259e2585998 100644
--- a/tests/fsharp/typecheck/sigs/neg119b.bsl
+++ b/tests/fsharp/typecheck/sigs/neg119b.bsl
@@ -1,4 +1,12 @@
 
-neg119b.fs(40,9,40,17): typecheck error FS0030: Value restriction. The value 'res2n3n4' has been inferred to have generic type
-    val res2n3n4: ^_a when (^_b or Applicatives.ZipList or ^_a) : (static member (<*>) : ^_b * Applicatives.ZipList -> ^_a) and (^_c or obj or ^_b) : (static member (<*>) : ^_c * obj -> ^_b) and (Applicatives.Ap or ^_c) : (static member Return: ^_c * Applicatives.Ap -> ((int -> int -> int) -> ^_c))    
-Either define 'res2n3n4' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.
+neg119b.fs(40,20,40,22): typecheck error FS0071: Type constraint mismatch when applying the default type 'obj' for a type inference variable. No overloads match for method 'Return'.
+
+Known return type: ((int -> int -> int) -> obj)
+
+Known type parameters: < obj , Applicatives.Ap >
+
+Available overloads:
+ - static member Applicatives.Ap.Return: ('r -> 'a) * Ap: Applicatives.Ap -> (('a -> 'r -> 'a2) -> 'a3 -> 'a -> 'r -> 'a2) // Argument at index 1 doesn't match
+ - static member Applicatives.Ap.Return: System.Tuple<'a> * Ap: Applicatives.Ap -> ('a -> System.Tuple<'a>) // Argument at index 1 doesn't match
+ - static member Applicatives.Ap.Return: r: ^R * obj -> ('a1 -> ^R) when ^R: (static member Return: 'a1 -> ^R) // Argument 'r' doesn't match
+ - static member Applicatives.Ap.Return: seq<'a> * Ap: Applicatives.Ap -> ('a -> seq<'a>) // Argument at index 1 doesn't match Consider adding further type constraints
diff --git a/tests/fsharp/typecheck/sigs/version50/neg20.bsl b/tests/fsharp/typecheck/sigs/version50/neg20.bsl
index 37e8f71a499..0711b546932 100644
--- a/tests/fsharp/typecheck/sigs/version50/neg20.bsl
+++ b/tests/fsharp/typecheck/sigs/version50/neg20.bsl
@@ -135,19 +135,19 @@ neg20.fs(108,12,108,16): typecheck error FS0001: Type mismatch. Expecting a
     'B * B -> 'a'    
 but given a
     'A * A -> Data'    
-The type 'B' does not match the type 'A'
+The type 'A' does not match the type 'B'
 
 neg20.fs(109,12,109,16): typecheck error FS0001: Type mismatch. Expecting a
     'A * B -> 'a'    
 but given a
     'A * A -> Data'    
-The type 'B' does not match the type 'A'
+The type 'A' does not match the type 'B'
 
 neg20.fs(110,12,110,16): typecheck error FS0001: Type mismatch. Expecting a
     'B * A -> 'a'    
 but given a
     'A * A -> Data'    
-The type 'B' does not match the type 'A'
+The type 'A' does not match the type 'B'
 
 neg20.fs(128,19,128,22): typecheck error FS0001: This expression was expected to have type
     'string'    
@@ -208,16 +208,6 @@ neg20.fs(183,29,183,34): typecheck error FS0001: This expression was expected to
 but here has type
     'obj'    
 
-neg20.fs(183,29,183,34): typecheck error FS0001: This expression was expected to have type
-    'int'    
-but here has type
-    'obj'    
-
-neg20.fs(183,35,183,40): typecheck error FS0001: This expression was expected to have type
-    'int'    
-but here has type
-    'obj'    
-
 neg20.fs(183,35,183,40): typecheck error FS0001: This expression was expected to have type
     'int'    
 but here has type
@@ -233,16 +223,6 @@ neg20.fs(184,28,184,33): typecheck error FS0001: This expression was expected to
 but here has type
     'obj'    
 
-neg20.fs(184,28,184,33): typecheck error FS0001: This expression was expected to have type
-    'int'    
-but here has type
-    'obj'    
-
-neg20.fs(184,34,184,39): typecheck error FS0001: This expression was expected to have type
-    'int'    
-but here has type
-    'obj'    
-
 neg20.fs(184,34,184,39): typecheck error FS0001: This expression was expected to have type
     'int'    
 but here has type
@@ -261,16 +241,6 @@ neg20.fs(189,29,189,34): typecheck error FS0001: This expression was expected to
 but here has type
     'obj'    
 
-neg20.fs(189,29,189,34): typecheck error FS0001: This expression was expected to have type
-    'string'    
-but here has type
-    'obj'    
-
-neg20.fs(189,35,189,40): typecheck error FS0001: This expression was expected to have type
-    'string'    
-but here has type
-    'obj'    
-
 neg20.fs(189,35,189,40): typecheck error FS0001: This expression was expected to have type
     'string'    
 but here has type
@@ -286,16 +256,6 @@ neg20.fs(190,28,190,33): typecheck error FS0001: This expression was expected to
 but here has type
     'obj'    
 
-neg20.fs(190,28,190,33): typecheck error FS0001: This expression was expected to have type
-    'string'    
-but here has type
-    'obj'    
-
-neg20.fs(190,34,190,39): typecheck error FS0001: This expression was expected to have type
-    'string'    
-but here has type
-    'obj'    
-
 neg20.fs(190,34,190,39): typecheck error FS0001: This expression was expected to have type
     'string'    
 but here has type

From 2cbdcd0d9100ff023a5c60d7d57525f53433a876 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Thu, 25 May 2023 13:29:35 +0100
Subject: [PATCH 10/59] update tests

---
 .../expected-help-output.bsl                  |  2 +
 ...p.Core.SurfaceArea.netstandard20.debug.bsl | 13 +++
 ...Core.SurfaceArea.netstandard20.release.bsl | 13 +++
 ...p.Core.SurfaceArea.netstandard21.debug.bsl | 15 +++-
 ...Core.SurfaceArea.netstandard21.release.bsl | 13 +++
 ...n_return_type_and_known_type_arguments.bsl | 32 +++++---
 tests/fsharp/typecheck/sigs/neg06.bsl         | 30 -------
 tests/fsharp/typecheck/sigs/neg07.bsl         | 12 +--
 tests/fsharp/typecheck/sigs/neg106.bsl        |  8 --
 tests/fsharp/typecheck/sigs/neg106.vsbsl      |  8 --
 tests/fsharp/typecheck/sigs/neg111.bsl        |  2 -
 tests/fsharp/typecheck/sigs/neg112.bsl        |  2 -
 tests/fsharp/typecheck/sigs/neg133.bsl        |  2 -
 tests/fsharp/typecheck/sigs/neg15.bsl         |  4 -
 tests/fsharp/typecheck/sigs/neg16.bsl         |  2 -
 tests/fsharp/typecheck/sigs/neg20.bsl         | 40 ---------
 tests/fsharp/typecheck/sigs/neg30.bsl         |  4 -
 tests/fsharp/typecheck/sigs/neg32.bsl         |  4 -
 tests/fsharp/typecheck/sigs/neg46.bsl         |  2 +-
 tests/fsharp/typecheck/sigs/neg48.bsl         | 22 -----
 tests/fsharp/typecheck/sigs/neg63.bsl         |  2 -
 tests/fsharp/typecheck/sigs/neg64.vsbsl       |  2 -
 tests/fsharp/typecheck/sigs/neg66.vsbsl       |  2 -
 tests/fsharp/typecheck/sigs/neg67.vsbsl       |  8 --
 tests/fsharp/typecheck/sigs/neg68.vsbsl       |  2 -
 tests/fsharp/typecheck/sigs/neg69.vsbsl       | 66 ---------------
 tests/fsharp/typecheck/sigs/neg70.vsbsl       |  2 -
 tests/fsharp/typecheck/sigs/neg71.vsbsl       |  8 --
 tests/fsharp/typecheck/sigs/neg72.vsbsl       |  2 -
 tests/fsharp/typecheck/sigs/neg73.vsbsl       |  2 -
 tests/fsharp/typecheck/sigs/neg74.bsl         | 26 ------
 tests/fsharp/typecheck/sigs/neg74.vsbsl       | 82 -------------------
 tests/fsharp/typecheck/sigs/neg75.bsl         |  4 -
 tests/fsharp/typecheck/sigs/neg75.vsbsl       | 14 ----
 tests/fsharp/typecheck/sigs/neg76.bsl         |  4 -
 tests/fsharp/typecheck/sigs/neg76.vsbsl       | 14 ----
 tests/fsharp/typecheck/sigs/neg77.bsl         |  2 -
 tests/fsharp/typecheck/sigs/neg77.vsbsl       |  8 --
 tests/fsharp/typecheck/sigs/neg79.vsbsl       |  2 -
 tests/fsharp/typecheck/sigs/neg80.vsbsl       |  2 -
 tests/fsharp/typecheck/sigs/neg81.bsl         |  2 -
 tests/fsharp/typecheck/sigs/neg81.vsbsl       | 16 ----
 tests/fsharp/typecheck/sigs/neg82.vsbsl       | 20 -----
 tests/fsharp/typecheck/sigs/neg83.bsl         |  2 -
 tests/fsharp/typecheck/sigs/neg83.vsbsl       | 12 ---
 tests/fsharp/typecheck/sigs/neg84.vsbsl       |  2 -
 tests/fsharp/typecheck/sigs/neg86.vsbsl       |  2 -
 tests/fsharp/typecheck/sigs/neg89.bsl         | 34 --------
 tests/fsharp/typecheck/sigs/neg90.bsl         |  2 -
 tests/fsharp/typecheck/sigs/neg95.bsl         |  2 +-
 tests/fsharp/typecheck/sigs/neg96.bsl         |  2 -
 tests/fsharp/typecheck/sigs/neg_byref_11.bsl  |  6 --
 tests/fsharp/typecheck/sigs/neg_byref_12.bsl  |  4 -
 tests/fsharp/typecheck/sigs/neg_byref_14.bsl  |  4 -
 tests/fsharp/typecheck/sigs/neg_byref_16.bsl  |  2 -
 tests/fsharp/typecheck/sigs/neg_byref_20.bsl  |  2 -
 tests/fsharp/typecheck/sigs/neg_byref_22.bsl  |  5 --
 tests/fsharp/typecheck/sigs/neg_byref_3.bsl   |  4 -
 tests/fsharp/typecheck/sigs/neg_byref_7.bsl   | 12 ---
 tests/fsharp/typecheck/sigs/neg_byref_8.bsl   | 12 ---
 60 files changed, 85 insertions(+), 546 deletions(-)

diff --git a/tests/FSharp.Compiler.Service.Tests/expected-help-output.bsl b/tests/FSharp.Compiler.Service.Tests/expected-help-output.bsl
index 6bb20c71312..cc174981296 100644
--- a/tests/FSharp.Compiler.Service.Tests/expected-help-output.bsl
+++ b/tests/FSharp.Compiler.Service.Tests/expected-help-output.bsl
@@ -106,6 +106,8 @@
 --nowarn:                      Disable specific warning messages
 --warnon:                      Enable specific warnings that may be
                                          off by default
+--checknulls[+|-]                        Enable nullness declarations and
+                                         checks
 --consolecolors[+|-]                     Output warning and error messages in
                                          color
 
diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl
index e373ae3440b..68798d068bb 100644
--- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl
+++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl
@@ -1910,6 +1910,19 @@ Microsoft.FSharp.Core.Operators: Void Decrement(Microsoft.FSharp.Core.FSharpRef`
 Microsoft.FSharp.Core.Operators: Void Ignore[T](T)
 Microsoft.FSharp.Core.Operators: Void Increment(Microsoft.FSharp.Core.FSharpRef`1[System.Int32])
 Microsoft.FSharp.Core.Operators: Void op_ColonEquals[T](Microsoft.FSharp.Core.FSharpRef`1[T], T)
+Microsoft.FSharp.Core.Operators: Boolean IsNullV[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullMatchPattern[T](T)
+Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullValueMatchPattern[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: System.Nullable`1[T] NullV[T]()
+Microsoft.FSharp.Core.Operators: System.Nullable`1[T] WithNullV[T](T)
+Microsoft.FSharp.Core.Operators: T DefaultIfNullV[T](T, System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: T DefaultIfNull[T](T, T)
+Microsoft.FSharp.Core.Operators: T NonNullQuickPattern[T](T)
+Microsoft.FSharp.Core.Operators: T NonNullQuickValuePattern[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: T NonNullV[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: T NonNull[T](T)
+Microsoft.FSharp.Core.Operators: T NullArgCheck[T](System.String, T)
+Microsoft.FSharp.Core.Operators: T WithNull[T](T)
 Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: FSharpFunc`3 Adapt(Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult]])
 Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult] Invoke(T1)
 Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: TResult Invoke(T1, T2)
diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl
index e314c7263a2..b04834e286e 100644
--- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl
+++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl
@@ -1909,6 +1909,19 @@ Microsoft.FSharp.Core.Operators: Void Decrement(Microsoft.FSharp.Core.FSharpRef`
 Microsoft.FSharp.Core.Operators: Void Ignore[T](T)
 Microsoft.FSharp.Core.Operators: Void Increment(Microsoft.FSharp.Core.FSharpRef`1[System.Int32])
 Microsoft.FSharp.Core.Operators: Void op_ColonEquals[T](Microsoft.FSharp.Core.FSharpRef`1[T], T)
+Microsoft.FSharp.Core.Operators: Boolean IsNullV[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullMatchPattern[T](T)
+Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullValueMatchPattern[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: System.Nullable`1[T] NullV[T]()
+Microsoft.FSharp.Core.Operators: System.Nullable`1[T] WithNullV[T](T)
+Microsoft.FSharp.Core.Operators: T DefaultIfNullV[T](T, System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: T DefaultIfNull[T](T, T)
+Microsoft.FSharp.Core.Operators: T NonNullQuickPattern[T](T)
+Microsoft.FSharp.Core.Operators: T NonNullQuickValuePattern[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: T NonNullV[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: T NonNull[T](T)
+Microsoft.FSharp.Core.Operators: T NullArgCheck[T](System.String, T)
+Microsoft.FSharp.Core.Operators: T WithNull[T](T)
 Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: FSharpFunc`3 Adapt(Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult]])
 Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult] Invoke(T1)
 Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: TResult Invoke(T1, T2)
diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl
index 29f826a24ba..06156cae486 100644
--- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl
+++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl
@@ -1002,7 +1002,7 @@ Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToTextWriter[T](Syste
 Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormat[T](Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit])
 Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceExpression[T](Microsoft.FSharp.Quotations.FSharpExpr`1[T])
 Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceUntypedExpression[T](Microsoft.FSharp.Quotations.FSharpExpr)
-Microsoft.FSharp.Core.ExtraTopLevelOperators: T[,] CreateArray2D[?,T](System.Collections.Generic.IEnumerable`1[?])
+Microsoft.FSharp.Core.ExtraTopLevelOperators: T[,] CreateArray2D[a,T](System.Collections.Generic.IEnumerable`1[a])
 Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: T1 Item
 Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: T1 get_Item()
 Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: T2 Item
@@ -1911,6 +1911,19 @@ Microsoft.FSharp.Core.Operators: Void Decrement(Microsoft.FSharp.Core.FSharpRef`
 Microsoft.FSharp.Core.Operators: Void Ignore[T](T)
 Microsoft.FSharp.Core.Operators: Void Increment(Microsoft.FSharp.Core.FSharpRef`1[System.Int32])
 Microsoft.FSharp.Core.Operators: Void op_ColonEquals[T](Microsoft.FSharp.Core.FSharpRef`1[T], T)
+Microsoft.FSharp.Core.Operators: Boolean IsNullV[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullMatchPattern[T](T)
+Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullValueMatchPattern[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: System.Nullable`1[T] NullV[T]()
+Microsoft.FSharp.Core.Operators: System.Nullable`1[T] WithNullV[T](T)
+Microsoft.FSharp.Core.Operators: T DefaultIfNullV[T](T, System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: T DefaultIfNull[T](T, T)
+Microsoft.FSharp.Core.Operators: T NonNullQuickPattern[T](T)
+Microsoft.FSharp.Core.Operators: T NonNullQuickValuePattern[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: T NonNullV[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: T NonNull[T](T)
+Microsoft.FSharp.Core.Operators: T NullArgCheck[T](System.String, T)
+Microsoft.FSharp.Core.Operators: T WithNull[T](T)
 Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: FSharpFunc`3 Adapt(Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult]])
 Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult] Invoke(T1)
 Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: TResult Invoke(T1, T2)
diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl
index 5114bd40b1d..6a8a86b0747 100644
--- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl
+++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl
@@ -1910,6 +1910,19 @@ Microsoft.FSharp.Core.Operators: Void Decrement(Microsoft.FSharp.Core.FSharpRef`
 Microsoft.FSharp.Core.Operators: Void Ignore[T](T)
 Microsoft.FSharp.Core.Operators: Void Increment(Microsoft.FSharp.Core.FSharpRef`1[System.Int32])
 Microsoft.FSharp.Core.Operators: Void op_ColonEquals[T](Microsoft.FSharp.Core.FSharpRef`1[T], T)
+Microsoft.FSharp.Core.Operators: Boolean IsNullV[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullMatchPattern[T](T)
+Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullValueMatchPattern[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: System.Nullable`1[T] NullV[T]()
+Microsoft.FSharp.Core.Operators: System.Nullable`1[T] WithNullV[T](T)
+Microsoft.FSharp.Core.Operators: T DefaultIfNullV[T](T, System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: T DefaultIfNull[T](T, T)
+Microsoft.FSharp.Core.Operators: T NonNullQuickPattern[T](T)
+Microsoft.FSharp.Core.Operators: T NonNullQuickValuePattern[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: T NonNullV[T](System.Nullable`1[T])
+Microsoft.FSharp.Core.Operators: T NonNull[T](T)
+Microsoft.FSharp.Core.Operators: T NullArgCheck[T](System.String, T)
+Microsoft.FSharp.Core.Operators: T WithNull[T](T)
 Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: FSharpFunc`3 Adapt(Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult]])
 Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult] Invoke(T1)
 Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: TResult Invoke(T1, T2)
diff --git a/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.bsl b/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.bsl
index 648183cdbde..698171eac59 100644
--- a/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.bsl
+++ b/tests/fsharp/typecheck/overloads/neg_known_return_type_and_known_type_arguments.bsl
@@ -1,14 +1,26 @@
 
-neg_known_return_type_and_known_type_arguments.fsx(16,57,16,67): typecheck error FS0043: The constraints 'struct' and 'null' are inconsistent
+neg_known_return_type_and_known_type_arguments.fsx(90,24,90,28): typecheck error FS0001: No overloads match for method 'Zero'.
 
-neg_known_return_type_and_known_type_arguments.fsx(52,54,52,64): typecheck error FS0043: The constraints 'struct' and 'null' are inconsistent
+Known return type: MonoidSample
 
-neg_known_return_type_and_known_type_arguments.fsx(54,54,54,64): typecheck error FS0043: The constraints 'struct' and 'null' are inconsistent
+Known type parameters: < MonoidSample , Zero >
 
-neg_known_return_type_and_known_type_arguments.fsx(77,30,77,98): typecheck error FS0043: This expression was expected to have type
-    ''Monoid'    
-but here has type
-    ''a -> 'a'    
-
-neg_known_return_type_and_known_type_arguments.fsx(90,24,90,28): typecheck error FS0039: The value or constructor 'zero' is not defined. Maybe you want one of the following:
-   Zero
+Available overloads:
+ - static member Zero.Zero: 'a array * Zero -> 'a array // Argument at index 1 doesn't match
+ - static member Zero.Zero: 'a list * Zero -> 'a list // Argument at index 1 doesn't match
+ - static member Zero.Zero: 'a option * Zero -> 'a option // Argument at index 1 doesn't match
+ - static member Zero.Zero: ('T -> ^Monoid) * Zero -> ('T -> ^Monoid) when (Zero or ^Monoid) : (static member Zero: ^Monoid * Zero -> ^Monoid) // Argument at index 1 doesn't match
+ - static member Zero.Zero: Async<^a> * Zero -> Async<^a> when (Zero or ^a) : (static member Zero: ^a * Zero -> ^a) // Argument at index 1 doesn't match
+ - static member Zero.Zero: Lazy<^a> * Zero -> Lazy<^a> when (Zero or ^a) : (static member Zero: ^a * Zero -> ^a) // Argument at index 1 doesn't match
+ - static member Zero.Zero: Map<'a,'b> * Zero -> Map<'a,'b> when 'a: comparison // Argument at index 1 doesn't match
+ - static member Zero.Zero: ResizeArray<'a> * Zero -> ResizeArray<'a> // Argument at index 1 doesn't match
+ - static member Zero.Zero: Set<'a> * Zero -> Set<'a> when 'a: comparison // Argument at index 1 doesn't match
+ - static member Zero.Zero: System.TimeSpan * Zero -> System.TimeSpan // Argument at index 1 doesn't match
+ - static member Zero.Zero: ^t * Default1 -> ('a1 -> 'a1) when ^t: null and ^t: struct // Argument at index 1 doesn't match
+ - static member Zero.Zero: ^t * Default1 -> ^t when ^t: (static member Zero: ^t) // Argument at index 1 doesn't match
+ - static member Zero.Zero: ^t * Default2 -> ('a1 -> 'a1) when ^t: null and ^t: struct // Argument at index 1 doesn't match
+ - static member Zero.Zero: ^t * Default2 -> ^t when (FromInt32 or ^t) : (static member FromInt32: ^t * FromInt32 -> (int32 -> ^t)) // Argument at index 1 doesn't match
+ - static member Zero.Zero: ^t * Default3 -> ^t when ^t: (static member Empty: ^t) // Argument at index 1 doesn't match
+ - static member Zero.Zero: seq<'a> * Zero -> seq<'a> // Argument at index 1 doesn't match
+ - static member Zero.Zero: string * Zero -> string // Argument at index 1 doesn't match
+ - static member Zero.Zero: unit * Zero -> unit // Argument at index 1 doesn't match
diff --git a/tests/fsharp/typecheck/sigs/neg06.bsl b/tests/fsharp/typecheck/sigs/neg06.bsl
index cc7fc113cfc..0443bd5c4a9 100644
--- a/tests/fsharp/typecheck/sigs/neg06.bsl
+++ b/tests/fsharp/typecheck/sigs/neg06.bsl
@@ -16,30 +16,16 @@ neg06.fs(37,6,37,29): typecheck error FS0954: This type definition involves an i
 
 neg06.fs(37,6,37,29): typecheck error FS0912: This declaration element is not permitted in an augmentation
 
-neg06.fs(37,6,37,29): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
-
 neg06.fs(42,6,42,30): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
 
 neg06.fs(46,5,46,29): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
 
 neg06.fs(42,6,42,30): typecheck error FS0912: This declaration element is not permitted in an augmentation
 
-neg06.fs(42,6,42,30): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
-
-neg06.fs(46,5,46,29): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
-
 neg06.fs(53,10,53,19): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
 
 neg06.fs(60,10,60,20): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
 
-neg06.fs(60,10,60,20): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
-
-neg06.fs(60,10,60,20): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
-
-neg06.fs(64,9,64,19): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
-
-neg06.fs(64,9,64,19): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
-
 neg06.fs(64,9,64,19): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
 
 neg06.fs(75,10,75,19): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
@@ -48,8 +34,6 @@ neg06.fs(80,10,80,25): typecheck error FS0953: This type definition involves an
 
 neg06.fs(90,10,90,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
 
-neg06.fs(90,10,90,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
 neg06.fs(94,10,94,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
 
 neg06.fs(99,10,99,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
@@ -58,26 +42,12 @@ neg06.fs(100,9,100,10): typecheck error FS0035: This construct is deprecated: Th
 
 neg06.fs(104,10,104,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
 
-neg06.fs(104,10,104,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg06.fs(108,10,108,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
 neg06.fs(108,10,108,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
 
 neg06.fs(112,10,112,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
 
 neg06.fs(117,10,117,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
 
-neg06.fs(117,10,117,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg06.fs(117,10,117,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg06.fs(118,9,118,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg06.fs(118,9,118,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg06.fs(118,9,118,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
 neg06.fs(118,9,118,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
 
 neg06.fs(118,9,118,10): typecheck error FS0035: This construct is deprecated: This type abbreviation has one or more declared type parameters that do not appear in the type being abbreviated. Type abbreviations must use all declared type parameters in the type being abbreviated. Consider removing one or more type parameters, or use a concrete type definition that wraps an underlying type, such as 'type C<'a> = C of ...'.
diff --git a/tests/fsharp/typecheck/sigs/neg07.bsl b/tests/fsharp/typecheck/sigs/neg07.bsl
index 618ebb131d0..265a19d7724 100644
--- a/tests/fsharp/typecheck/sigs/neg07.bsl
+++ b/tests/fsharp/typecheck/sigs/neg07.bsl
@@ -1,8 +1,6 @@
 
 neg07.fs(7,10,7,29): typecheck error FS0049: Uppercase variable identifiers should not generally be used in patterns, and may indicate a missing open declaration or a misspelt pattern name.
 
-neg07.fs(7,10,7,29): typecheck error FS0049: Uppercase variable identifiers should not generally be used in patterns, and may indicate a missing open declaration or a misspelt pattern name.
-
 neg07.fs(24,13,24,23): typecheck error FS0039: The value or constructor 'UnionCase1' is not defined. Maybe you want one of the following:
    X.UnionCase1
 
@@ -27,16 +25,18 @@ neg07.fs(46,15,46,27): typecheck error FS0039: The record label 'RecordLabel1' i
 neg07.fs(46,33,46,45): typecheck error FS0039: The record label 'RecordLabel2' is not defined. Maybe you want one of the following:
    R.RecordLabel2
 
-neg07.fs(47,17,47,55): typecheck error FS0025: Incomplete pattern matches on this expression.
-neg07.fs(47,59,47,60): typecheck error FS0039: The value or constructor 'a' is not defined.
-neg07.fs(47,63,47,64): typecheck error FS0039: The value or constructor 'b' is not defined.
-
 neg07.fs(47,19,47,31): typecheck error FS0039: The record label 'RecordLabel1' is not defined. Maybe you want one of the following:
    R.RecordLabel1
 
 neg07.fs(47,37,47,49): typecheck error FS0039: The record label 'RecordLabel2' is not defined. Maybe you want one of the following:
    R.RecordLabel2
 
+neg07.fs(47,59,47,60): typecheck error FS0039: The value or constructor 'a' is not defined.
+
+neg07.fs(47,63,47,64): typecheck error FS0039: The value or constructor 'b' is not defined.
+
+neg07.fs(47,17,47,55): typecheck error FS0025: Incomplete pattern matches on this expression.
+
 neg07.fs(57,10,57,17): typecheck error FS1196: The 'UseNullAsTrueValue' attribute flag may only be used with union types that have one nullary case and at least one non-nullary case
 
 neg07.fs(64,10,64,18): typecheck error FS1196: The 'UseNullAsTrueValue' attribute flag may only be used with union types that have one nullary case and at least one non-nullary case
diff --git a/tests/fsharp/typecheck/sigs/neg106.bsl b/tests/fsharp/typecheck/sigs/neg106.bsl
index 6630d22d110..ab3400ccd97 100644
--- a/tests/fsharp/typecheck/sigs/neg106.bsl
+++ b/tests/fsharp/typecheck/sigs/neg106.bsl
@@ -172,11 +172,3 @@ neg106.fs(147,34,147,44): typecheck error FS1204: This construct is for use in t
 neg106.fs(148,34,148,44): typecheck error FS1204: This construct is for use in the FSharp.Core library and should not be used directly
 
 neg106.fs(149,34,149,44): typecheck error FS1204: This construct is for use in the FSharp.Core library and should not be used directly
-
-neg106.fs(146,34,146,47): typecheck error FS1204: This construct is for use in the FSharp.Core library and should not be used directly
-
-neg106.fs(147,34,147,44): typecheck error FS1204: This construct is for use in the FSharp.Core library and should not be used directly
-
-neg106.fs(148,34,148,44): typecheck error FS1204: This construct is for use in the FSharp.Core library and should not be used directly
-
-neg106.fs(149,34,149,44): typecheck error FS1204: This construct is for use in the FSharp.Core library and should not be used directly
diff --git a/tests/fsharp/typecheck/sigs/neg106.vsbsl b/tests/fsharp/typecheck/sigs/neg106.vsbsl
index 6630d22d110..ab3400ccd97 100644
--- a/tests/fsharp/typecheck/sigs/neg106.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg106.vsbsl
@@ -172,11 +172,3 @@ neg106.fs(147,34,147,44): typecheck error FS1204: This construct is for use in t
 neg106.fs(148,34,148,44): typecheck error FS1204: This construct is for use in the FSharp.Core library and should not be used directly
 
 neg106.fs(149,34,149,44): typecheck error FS1204: This construct is for use in the FSharp.Core library and should not be used directly
-
-neg106.fs(146,34,146,47): typecheck error FS1204: This construct is for use in the FSharp.Core library and should not be used directly
-
-neg106.fs(147,34,147,44): typecheck error FS1204: This construct is for use in the FSharp.Core library and should not be used directly
-
-neg106.fs(148,34,148,44): typecheck error FS1204: This construct is for use in the FSharp.Core library and should not be used directly
-
-neg106.fs(149,34,149,44): typecheck error FS1204: This construct is for use in the FSharp.Core library and should not be used directly
diff --git a/tests/fsharp/typecheck/sigs/neg111.bsl b/tests/fsharp/typecheck/sigs/neg111.bsl
index c5048f7c299..9ad833b8054 100644
--- a/tests/fsharp/typecheck/sigs/neg111.bsl
+++ b/tests/fsharp/typecheck/sigs/neg111.bsl
@@ -1,8 +1,6 @@
 
 neg111.fs(2,552,2,557): typecheck error FS0039: The type 'fail1' is not defined.
 
-neg111.fs(2,552,2,557): typecheck error FS0039: The type 'fail1' is not defined.
-
 neg111.fs(3,624,3,629): typecheck error FS0039: The value or constructor 'fail2' is not defined. Maybe you want one of the following:
    Failure
    failwith
diff --git a/tests/fsharp/typecheck/sigs/neg112.bsl b/tests/fsharp/typecheck/sigs/neg112.bsl
index 23711fb3b4d..59b02d90e0c 100644
--- a/tests/fsharp/typecheck/sigs/neg112.bsl
+++ b/tests/fsharp/typecheck/sigs/neg112.bsl
@@ -2,5 +2,3 @@
 neg112.fs(20,49,20,62): typecheck error FS0001: A type parameter is missing a constraint 'when (Tuple or ^options) : (static member TupleMap: ^options * Tuple -> (('item -> ^value) -> ^values))'
 
 neg112.fs(20,31,20,39): typecheck error FS0043: A type parameter is missing a constraint 'when (Tuple or ^options) : (static member TupleMap: ^options * Tuple -> (('item -> ^value) -> ^values))'
-
-neg112.fs(20,31,20,39): typecheck error FS0043: A type parameter is missing a constraint 'when (Tuple or ^options) : (static member TupleMap: ^options * Tuple -> (('item -> ^value) -> ^values))'
diff --git a/tests/fsharp/typecheck/sigs/neg133.bsl b/tests/fsharp/typecheck/sigs/neg133.bsl
index aa3f1bdf3d6..f037c70f065 100644
--- a/tests/fsharp/typecheck/sigs/neg133.bsl
+++ b/tests/fsharp/typecheck/sigs/neg133.bsl
@@ -20,5 +20,3 @@ neg133.fs(63,7,63,19): typecheck error FS0026: This rule will never be matched
 neg133.fs(69,7,69,21): typecheck error FS0026: This rule will never be matched
 
 neg133.fs(76,10,76,11): typecheck error FS0957: One or more of the declared type parameters for this type extension have a missing or wrong type constraint not matching the original type constraints on 'A<_,_,_>'
-
-neg133.fs(76,10,76,11): typecheck error FS0957: One or more of the declared type parameters for this type extension have a missing or wrong type constraint not matching the original type constraints on 'A<_,_,_>'
diff --git a/tests/fsharp/typecheck/sigs/neg15.bsl b/tests/fsharp/typecheck/sigs/neg15.bsl
index 055ddf9fcc3..3089124970c 100644
--- a/tests/fsharp/typecheck/sigs/neg15.bsl
+++ b/tests/fsharp/typecheck/sigs/neg15.bsl
@@ -15,10 +15,6 @@ neg15.fs(110,17,110,45): typecheck error FS0491: The member or object constructo
 
 neg15.fs(111,17,111,52): typecheck error FS1092: The type 'PrivateRecordType' is not accessible from this code location
 
-neg15.fs(111,17,111,52): typecheck error FS1092: The type 'PrivateRecordType' is not accessible from this code location
-
-neg15.fs(112,18,112,78): typecheck error FS1093: The union cases or fields of the type 'RecordTypeWithPrivateRepresentation' are not accessible from this code location
-
 neg15.fs(112,18,112,78): typecheck error FS1093: The union cases or fields of the type 'RecordTypeWithPrivateRepresentation' are not accessible from this code location
 
 neg15.fs(113,17,113,76): typecheck error FS1093: The union cases or fields of the type 'RecordTypeWithPrivateRepresentation' are not accessible from this code location
diff --git a/tests/fsharp/typecheck/sigs/neg16.bsl b/tests/fsharp/typecheck/sigs/neg16.bsl
index c32ad022d1f..fa193383e45 100644
--- a/tests/fsharp/typecheck/sigs/neg16.bsl
+++ b/tests/fsharp/typecheck/sigs/neg16.bsl
@@ -3,8 +3,6 @@ neg16.fs(7,13,7,16): typecheck error FS0644: Namespaces cannot contain extension
 
 neg16.fs(23,10,23,11): typecheck error FS0935: Types with the 'AllowNullLiteral' attribute may only inherit from or implement types which also allow the use of the null literal
 
-neg16.fs(23,10,23,11): typecheck error FS0935: Types with the 'AllowNullLiteral' attribute may only inherit from or implement types which also allow the use of the null literal
-
 neg16.fs(35,10,35,11): typecheck error FS0934: Records, union, abbreviations and struct types cannot have the 'AllowNullLiteral' attribute
 
 neg16.fs(38,10,38,11): typecheck error FS0934: Records, union, abbreviations and struct types cannot have the 'AllowNullLiteral' attribute
diff --git a/tests/fsharp/typecheck/sigs/neg20.bsl b/tests/fsharp/typecheck/sigs/neg20.bsl
index 095ec90fd47..45cf9fa1806 100644
--- a/tests/fsharp/typecheck/sigs/neg20.bsl
+++ b/tests/fsharp/typecheck/sigs/neg20.bsl
@@ -158,16 +158,6 @@ neg20.fs(183,29,183,34): typecheck error FS0001: This expression was expected to
 but here has type
     'obj'    
 
-neg20.fs(183,29,183,34): typecheck error FS0001: This expression was expected to have type
-    'int'    
-but here has type
-    'obj'    
-
-neg20.fs(183,35,183,40): typecheck error FS0001: This expression was expected to have type
-    'int'    
-but here has type
-    'obj'    
-
 neg20.fs(183,35,183,40): typecheck error FS0001: This expression was expected to have type
     'int'    
 but here has type
@@ -184,16 +174,6 @@ neg20.fs(184,28,184,33): typecheck error FS0001: This expression was expected to
 but here has type
     'obj'    
 
-neg20.fs(184,28,184,33): typecheck error FS0001: This expression was expected to have type
-    'int'    
-but here has type
-    'obj'    
-
-neg20.fs(184,34,184,39): typecheck error FS0001: This expression was expected to have type
-    'int'    
-but here has type
-    'obj'    
-
 neg20.fs(184,34,184,39): typecheck error FS0001: This expression was expected to have type
     'int'    
 but here has type
@@ -212,16 +192,6 @@ neg20.fs(189,29,189,34): typecheck error FS0001: This expression was expected to
 but here has type
     'obj'    
 
-neg20.fs(189,29,189,34): typecheck error FS0001: This expression was expected to have type
-    'string'    
-but here has type
-    'obj'    
-
-neg20.fs(189,35,189,40): typecheck error FS0001: This expression was expected to have type
-    'string'    
-but here has type
-    'obj'    
-
 neg20.fs(189,35,189,40): typecheck error FS0001: This expression was expected to have type
     'string'    
 but here has type
@@ -238,16 +208,6 @@ neg20.fs(190,28,190,33): typecheck error FS0001: This expression was expected to
 but here has type
     'obj'    
 
-neg20.fs(190,28,190,33): typecheck error FS0001: This expression was expected to have type
-    'string'    
-but here has type
-    'obj'    
-
-neg20.fs(190,34,190,39): typecheck error FS0001: This expression was expected to have type
-    'string'    
-but here has type
-    'obj'    
-
 neg20.fs(190,34,190,39): typecheck error FS0001: This expression was expected to have type
     'string'    
 but here has type
diff --git a/tests/fsharp/typecheck/sigs/neg30.bsl b/tests/fsharp/typecheck/sigs/neg30.bsl
index b958db2e367..a88609e030c 100644
--- a/tests/fsharp/typecheck/sigs/neg30.bsl
+++ b/tests/fsharp/typecheck/sigs/neg30.bsl
@@ -27,8 +27,4 @@ neg30.fs(64,13,64,29): typecheck error FS0001: A generic construct requires that
 
 neg30.fs(71,12,71,35): typecheck error FS0120: hello!
 
-neg30.fs(71,12,71,35): typecheck error FS0120: hello!
-
-neg30.fs(71,12,71,35): typecheck error FS0120: hello!
-
 neg30.fs(78,13,78,37): typecheck error FS10021: hello!
diff --git a/tests/fsharp/typecheck/sigs/neg32.bsl b/tests/fsharp/typecheck/sigs/neg32.bsl
index 09e6050c790..50625a4882d 100644
--- a/tests/fsharp/typecheck/sigs/neg32.bsl
+++ b/tests/fsharp/typecheck/sigs/neg32.bsl
@@ -45,10 +45,6 @@ neg32.fs(59,4,59,33): typecheck error FS0671: A property cannot have explicit ty
 
 neg32.fs(62,10,62,12): typecheck error FS0039: The type parameter 'T is not defined.
 
-neg32.fs(62,10,62,12): typecheck error FS0039: The type parameter 'T is not defined.
-
-neg32.fs(65,11,65,13): typecheck error FS0039: The type parameter 'T is not defined.
-
 neg32.fs(65,11,65,13): typecheck error FS0039: The type parameter 'T is not defined.
 
 neg32.fs(69,65,69,86): typecheck error FS0033: The non-generic type 'System.EventArgs' does not expect any type arguments, but here is given 1 type argument(s)
diff --git a/tests/fsharp/typecheck/sigs/neg46.bsl b/tests/fsharp/typecheck/sigs/neg46.bsl
index bb3cafeccb3..1bdf9fbc95b 100644
--- a/tests/fsharp/typecheck/sigs/neg46.bsl
+++ b/tests/fsharp/typecheck/sigs/neg46.bsl
@@ -37,4 +37,4 @@ neg46.fs(64,8,64,26): typecheck error FS0912: This declaration element is not pe
 
 neg46.fs(68,18,68,36): typecheck error FS0909: All implemented interfaces should be declared on the initial declaration of the type
 
-neg46.fs(73,18,73,36): typecheck error FS0909: All implemented interfaces should be declared on the initial declaration of the type
\ No newline at end of file
+neg46.fs(73,18,73,36): typecheck error FS0909: All implemented interfaces should be declared on the initial declaration of the type
diff --git a/tests/fsharp/typecheck/sigs/neg48.bsl b/tests/fsharp/typecheck/sigs/neg48.bsl
index 4d9e739cc0d..a6f0847486c 100644
--- a/tests/fsharp/typecheck/sigs/neg48.bsl
+++ b/tests/fsharp/typecheck/sigs/neg48.bsl
@@ -9,50 +9,28 @@ neg48.fs(52,21,52,26): typecheck error FS0023: The member 'Item2' can not be def
 
 neg48.fs(56,16,56,20): typecheck error FS0023: The member 'Tags' can not be defined because the name 'Tags' clashes with the generated type 'Tags' in this type or module
 
-neg48.fs(56,16,56,20): typecheck error FS0023: The member 'Tags' can not be defined because the name 'Tags' clashes with the generated type 'Tags' in this type or module
-
-neg48.fs(60,21,60,25): typecheck error FS0023: The member 'Tags' can not be defined because the name 'Tags' clashes with the generated type 'Tags' in this type or module
-
 neg48.fs(60,21,60,25): typecheck error FS0023: The member 'Tags' can not be defined because the name 'Tags' clashes with the generated type 'Tags' in this type or module
 
 neg48.fs(64,16,64,19): typecheck error FS0023: The member 'Tag' can not be defined because the name 'Tag' clashes with the generated property 'Tag' in this type or module
 
-neg48.fs(64,16,64,19): typecheck error FS0023: The member 'Tag' can not be defined because the name 'Tag' clashes with the generated property 'Tag' in this type or module
-
 neg48.fs(68,16,68,20): typecheck error FS0023: The member 'Item' can not be defined because the name 'Item' clashes with the generated property 'Item' in this type or module
 
 neg48.fs(72,21,72,25): typecheck error FS0023: The member 'Item' can not be defined because the name 'Item' clashes with the generated property 'Item' in this type or module
 
 neg48.fs(76,16,76,20): typecheck error FS0023: The member 'Tags' can not be defined because the name 'Tags' clashes with the generated type 'Tags' in this type or module
 
-neg48.fs(76,16,76,20): typecheck error FS0023: The member 'Tags' can not be defined because the name 'Tags' clashes with the generated type 'Tags' in this type or module
-
 neg48.fs(80,21,80,25): typecheck error FS0023: The member 'Tags' can not be defined because the name 'Tags' clashes with the generated type 'Tags' in this type or module
 
-neg48.fs(80,21,80,25): typecheck error FS0023: The member 'Tags' can not be defined because the name 'Tags' clashes with the generated type 'Tags' in this type or module
-
-neg48.fs(84,16,84,19): typecheck error FS0023: The member 'Tag' can not be defined because the name 'Tag' clashes with the generated property 'Tag' in this type or module
-
 neg48.fs(84,16,84,19): typecheck error FS0023: The member 'Tag' can not be defined because the name 'Tag' clashes with the generated property 'Tag' in this type or module
 
 neg48.fs(88,21,88,24): typecheck error FS0023: The member 'Tag' can not be defined because the name 'Tag' clashes with the generated property 'Tag' in this type or module
 
-neg48.fs(88,21,88,24): typecheck error FS0023: The member 'Tag' can not be defined because the name 'Tag' clashes with the generated property 'Tag' in this type or module
-
-neg48.fs(92,16,92,20): typecheck error FS0023: The member 'Tags' can not be defined because the name 'Tags' clashes with the generated type 'Tags' in this type or module
-
 neg48.fs(92,16,92,20): typecheck error FS0023: The member 'Tags' can not be defined because the name 'Tags' clashes with the generated type 'Tags' in this type or module
 
 neg48.fs(96,16,96,19): typecheck error FS0023: The member 'Tag' can not be defined because the name 'Tag' clashes with the generated property 'Tag' in this type or module
 
-neg48.fs(96,16,96,19): typecheck error FS0023: The member 'Tag' can not be defined because the name 'Tag' clashes with the generated property 'Tag' in this type or module
-
-neg48.fs(102,16,102,19): typecheck error FS0023: The member 'Tag' can not be defined because the name 'Tag' clashes with the generated property 'Tag' in this type or module
-
 neg48.fs(102,16,102,19): typecheck error FS0023: The member 'Tag' can not be defined because the name 'Tag' clashes with the generated property 'Tag' in this type or module
 
 neg48.fs(105,16,105,20): typecheck error FS0023: The member 'Tags' can not be defined because the name 'Tags' clashes with the generated type 'Tags' in this type or module
 
-neg48.fs(105,16,105,20): typecheck error FS0023: The member 'Tags' can not be defined because the name 'Tags' clashes with the generated type 'Tags' in this type or module
-
 neg48.fs(108,16,108,20): typecheck error FS0023: The member 'Item' can not be defined because the name 'Item' clashes with the generated property 'Item' in this type or module
diff --git a/tests/fsharp/typecheck/sigs/neg63.bsl b/tests/fsharp/typecheck/sigs/neg63.bsl
index 194fbe88771..300565f5df2 100644
--- a/tests/fsharp/typecheck/sigs/neg63.bsl
+++ b/tests/fsharp/typecheck/sigs/neg63.bsl
@@ -16,5 +16,3 @@ neg63.fs(18,6,18,7): typecheck error FS3209: The address of the variable 'x' or
 neg63.fs(26,6,26,10): typecheck error FS3209: The address of the variable 'addr' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.
 
 neg63.fs(30,24,30,25): typecheck error FS3232: Struct members cannot return the address of fields of the struct by reference
-
-neg63.fs(30,24,30,25): typecheck error FS3232: Struct members cannot return the address of fields of the struct by reference
diff --git a/tests/fsharp/typecheck/sigs/neg64.vsbsl b/tests/fsharp/typecheck/sigs/neg64.vsbsl
index 0b2bac35a59..e9578dc3735 100644
--- a/tests/fsharp/typecheck/sigs/neg64.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg64.vsbsl
@@ -1,4 +1,2 @@
 
 neg64.fsx(32,32,32,33): parse error FS0010: Unexpected symbol ')' in if/then/else expression
-
-neg64.fsx(32,32,32,33): parse error FS0010: Unexpected symbol ')' in if/then/else expression
diff --git a/tests/fsharp/typecheck/sigs/neg66.vsbsl b/tests/fsharp/typecheck/sigs/neg66.vsbsl
index 9c5184da298..0c27ea51528 100644
--- a/tests/fsharp/typecheck/sigs/neg66.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg66.vsbsl
@@ -1,6 +1,4 @@
 
 neg66.fsx(43,4,43,5): parse error FS0010: Unexpected symbol ')' in definition. Expected incomplete structured construct at or before this point or other token.
 
-neg66.fsx(43,4,43,5): parse error FS0010: Unexpected symbol ')' in definition. Expected incomplete structured construct at or before this point or other token.
-
 neg66.fsx(30,1,38,33): typecheck error FS0003: This value is not a function and cannot be applied.
diff --git a/tests/fsharp/typecheck/sigs/neg67.vsbsl b/tests/fsharp/typecheck/sigs/neg67.vsbsl
index 9d8da15b935..6f2922050be 100644
--- a/tests/fsharp/typecheck/sigs/neg67.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg67.vsbsl
@@ -7,14 +7,6 @@ neg67.fsx(42,17,42,34): parse error FS0597: Successive arguments should be separ
 
 neg67.fsx(42,35,42,36): parse error FS0010: Unexpected symbol '}' in definition. Expected incomplete structured construct at or before this point or other token.
 
-neg67.fsx(41,36,41,37): parse error FS0010: Incomplete structured construct at or before this point in expression. Expected '}' or other token.
-
-neg67.fsx(41,15,41,16): parse error FS0604: Unmatched '{'
-
-neg67.fsx(42,17,42,34): parse error FS0597: Successive arguments should be separated by spaces or tupled, and arguments involving function or method applications should be parenthesized
-
-neg67.fsx(42,35,42,36): parse error FS0010: Unexpected symbol '}' in definition. Expected incomplete structured construct at or before this point or other token.
-
 neg67.fsx(41,9,41,14): typecheck error FS0193: Type constraint mismatch. The type 
     'Async'    
 is not compatible with type
diff --git a/tests/fsharp/typecheck/sigs/neg68.vsbsl b/tests/fsharp/typecheck/sigs/neg68.vsbsl
index 15966211aa0..b55d58ee143 100644
--- a/tests/fsharp/typecheck/sigs/neg68.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg68.vsbsl
@@ -1,8 +1,6 @@
 
 neg68.fsx(71,46,71,47): parse error FS0010: Unexpected symbol ')' in binding. Expected incomplete structured construct at or before this point or other token.
 
-neg68.fsx(71,46,71,47): parse error FS0010: Unexpected symbol ')' in binding. Expected incomplete structured construct at or before this point or other token.
-
 neg68.fsx(123,40,123,41): typecheck error FS0001: The type 'bool' does not match the type 'float<'u>'
 
 neg68.fsx(123,38,123,39): typecheck error FS0043: The type 'bool' does not match the type 'float<'u>'
diff --git a/tests/fsharp/typecheck/sigs/neg69.vsbsl b/tests/fsharp/typecheck/sigs/neg69.vsbsl
index 7c5c0a5fecb..e8270894f00 100644
--- a/tests/fsharp/typecheck/sigs/neg69.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg69.vsbsl
@@ -64,69 +64,3 @@ neg69.fsx(212,1,212,4): parse error FS0058: Possible incorrect indentation: this
 neg69.fsx(221,1,221,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (212:1). Try indenting this token further or using standard formatting conventions.
 
 neg69.fsx(242,1,242,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (221:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(88,43,88,44): parse error FS1241: Expected type argument or static argument
-
-neg69.fsx(88,44,88,45): parse error FS0010: Unexpected symbol '>' in type definition. Expected '=' or other token.
-
-neg69.fsx(94,5,94,8): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (93:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(94,5,94,8): parse error FS0010: Unexpected keyword 'let' or 'use' in implementation file
-
-neg69.fsx(95,5,95,8): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (94:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(96,5,96,8): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (95:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(98,5,98,11): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(98,19,98,20): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(99,5,99,11): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(100,5,100,11): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(101,5,101,11): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(102,5,102,11): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(104,5,104,14): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(113,1,113,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(168,1,168,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(170,1,170,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (168:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(171,1,171,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (170:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(172,1,172,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (171:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(173,1,173,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (172:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(174,1,174,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (173:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(176,1,176,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (174:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(177,1,177,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (176:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(178,1,178,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (177:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(180,1,180,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (178:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(181,1,181,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (180:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(182,1,182,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (181:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(183,1,183,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (182:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(185,1,185,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(194,1,194,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (185:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(203,1,203,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (194:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(212,1,212,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (203:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(221,1,221,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (212:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(242,1,242,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (221:1). Try indenting this token further or using standard formatting conventions.
diff --git a/tests/fsharp/typecheck/sigs/neg70.vsbsl b/tests/fsharp/typecheck/sigs/neg70.vsbsl
index 5103887eb35..16c15ba3780 100644
--- a/tests/fsharp/typecheck/sigs/neg70.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg70.vsbsl
@@ -1,4 +1,2 @@
 
 neg70.fsx(109,64,109,65): parse error FS0010: Unexpected symbol ')' in binding. Expected incomplete structured construct at or before this point or other token.
-
-neg70.fsx(109,64,109,65): parse error FS0010: Unexpected symbol ')' in binding. Expected incomplete structured construct at or before this point or other token.
diff --git a/tests/fsharp/typecheck/sigs/neg71.vsbsl b/tests/fsharp/typecheck/sigs/neg71.vsbsl
index bbdad6e76ff..0af53931890 100644
--- a/tests/fsharp/typecheck/sigs/neg71.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg71.vsbsl
@@ -7,14 +7,6 @@ neg71.fsx(230,1,230,13): parse error FS0010: Unexpected identifier in member def
 
 neg71.fsx(128,5,128,81): parse info FS3520: XML comment is not placed on a valid language element.
 
-neg71.fsx(110,43,110,44): parse error FS0010: Unexpected symbol ')' in expression. Expected incomplete structured construct at or before this point or other token.
-
-neg71.fsx(166,24,168,1): parse error FS0010: Incomplete structured construct at or before this point in member definition. Expected incomplete structured construct at or before this point, 'end' or other token.
-
-neg71.fsx(230,1,230,13): parse error FS0010: Unexpected identifier in member definition
-
-neg71.fsx(128,5,128,81): parse info FS3520: XML comment is not placed on a valid language element.
-
 neg71.fsx(168,1,168,28): typecheck error FS0960: 'let' and 'do' bindings must come before member and interface definitions in type definitions
 
 neg71.fsx(168,9,168,18): typecheck error FS0039: The value or constructor 'Simulator' is not defined.
diff --git a/tests/fsharp/typecheck/sigs/neg72.vsbsl b/tests/fsharp/typecheck/sigs/neg72.vsbsl
index 29fc279ec42..e7c11aa1adf 100644
--- a/tests/fsharp/typecheck/sigs/neg72.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg72.vsbsl
@@ -1,4 +1,2 @@
 
 neg72.fsx(144,106,144,107): parse error FS0010: Unexpected symbol ')' in binding. Expected incomplete structured construct at or before this point or other token.
-
-neg72.fsx(144,106,144,107): parse error FS0010: Unexpected symbol ')' in binding. Expected incomplete structured construct at or before this point or other token.
diff --git a/tests/fsharp/typecheck/sigs/neg73.vsbsl b/tests/fsharp/typecheck/sigs/neg73.vsbsl
index b11767d5921..8ea9d755311 100644
--- a/tests/fsharp/typecheck/sigs/neg73.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg73.vsbsl
@@ -1,4 +1,2 @@
 
 neg73.fsx(153,79,153,80): parse error FS0010: Unexpected symbol ']' in binding. Expected incomplete structured construct at or before this point or other token.
-
-neg73.fsx(153,79,153,80): parse error FS0010: Unexpected symbol ']' in binding. Expected incomplete structured construct at or before this point or other token.
diff --git a/tests/fsharp/typecheck/sigs/neg74.bsl b/tests/fsharp/typecheck/sigs/neg74.bsl
index 2a3f2816a0a..00cb444ed16 100644
--- a/tests/fsharp/typecheck/sigs/neg74.bsl
+++ b/tests/fsharp/typecheck/sigs/neg74.bsl
@@ -1,56 +1,30 @@
 
 neg74.fsx(185,1,185,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(185,1,185,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(194,1,194,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(194,1,194,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
 neg74.fsx(203,1,203,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(203,1,203,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(212,1,212,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(212,1,212,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(221,1,221,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(221,1,221,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
 neg74.fsx(230,1,230,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(230,1,230,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(231,1,231,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(231,1,231,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
 neg74.fsx(232,1,232,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(232,1,232,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(233,1,233,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(233,1,233,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(234,1,234,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(234,1,234,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
 neg74.fsx(236,1,236,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(236,1,236,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(241,1,241,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(241,1,241,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
 neg74.fsx(241,1,241,3): parse error FS0010: Unexpected symbol '[<' in binding. Expected incomplete structured construct at or before this point or other token.
 
 neg74.fsx(242,1,242,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(242,1,242,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(254,1,254,1): parse error FS0010: Incomplete structured construct at or before this point in implementation file
diff --git a/tests/fsharp/typecheck/sigs/neg74.vsbsl b/tests/fsharp/typecheck/sigs/neg74.vsbsl
index 609fcc1264e..02db21c8eba 100644
--- a/tests/fsharp/typecheck/sigs/neg74.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg74.vsbsl
@@ -1,114 +1,32 @@
 
 neg74.fsx(185,1,185,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(185,1,185,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(194,1,194,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(194,1,194,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(203,1,203,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(203,1,203,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(212,1,212,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(212,1,212,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(221,1,221,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(221,1,221,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(230,1,230,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(230,1,230,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(231,1,231,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(231,1,231,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(232,1,232,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(232,1,232,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(233,1,233,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(233,1,233,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(234,1,234,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(234,1,234,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(236,1,236,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(236,1,236,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(241,1,241,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(241,1,241,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(241,1,241,3): parse error FS0010: Unexpected symbol '[<' in binding. Expected incomplete structured construct at or before this point or other token.
-
-neg74.fsx(242,1,242,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(242,1,242,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(254,1,254,1): parse error FS0010: Incomplete structured construct at or before this point in implementation file
-
-neg74.fsx(185,1,185,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(185,1,185,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(194,1,194,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(194,1,194,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
 neg74.fsx(203,1,203,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(203,1,203,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(212,1,212,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(212,1,212,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
 neg74.fsx(221,1,221,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(221,1,221,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(230,1,230,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(230,1,230,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
 neg74.fsx(231,1,231,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(231,1,231,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(232,1,232,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(232,1,232,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
 neg74.fsx(233,1,233,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(233,1,233,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(234,1,234,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(234,1,234,13): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
-neg74.fsx(236,1,236,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(236,1,236,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
 neg74.fsx(241,1,241,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(241,1,241,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(241,1,241,3): parse error FS0010: Unexpected symbol '[<' in binding. Expected incomplete structured construct at or before this point or other token.
 
 neg74.fsx(242,1,242,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
 
-neg74.fsx(242,1,242,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:28). Try indenting this token further or using standard formatting conventions.
-
 neg74.fsx(254,1,254,1): parse error FS0010: Incomplete structured construct at or before this point in implementation file
 
 neg74.fsx(183,52,183,53): typecheck error FS0043: The type 'unit' does not match the type 'float'
diff --git a/tests/fsharp/typecheck/sigs/neg75.bsl b/tests/fsharp/typecheck/sigs/neg75.bsl
index b46bf301d19..f3d89126ea4 100644
--- a/tests/fsharp/typecheck/sigs/neg75.bsl
+++ b/tests/fsharp/typecheck/sigs/neg75.bsl
@@ -1,10 +1,6 @@
 
 neg75.fsx(154,24,154,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
 
-neg75.fsx(154,24,154,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
-neg75.fsx(155,24,155,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
 neg75.fsx(155,24,155,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
 
 neg75.fsx(153,24,153,27): parse error FS0588: The block following this 'let' is unfinished. Every code block is an expression and must have a result. 'let' cannot be the final code element in a block. Consider giving this block an explicit result.
diff --git a/tests/fsharp/typecheck/sigs/neg75.vsbsl b/tests/fsharp/typecheck/sigs/neg75.vsbsl
index fbafdc0a328..f3d89126ea4 100644
--- a/tests/fsharp/typecheck/sigs/neg75.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg75.vsbsl
@@ -1,20 +1,6 @@
 
 neg75.fsx(154,24,154,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
 
-neg75.fsx(154,24,154,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
-neg75.fsx(155,24,155,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
-neg75.fsx(155,24,155,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
-neg75.fsx(153,24,153,27): parse error FS0588: The block following this 'let' is unfinished. Every code block is an expression and must have a result. 'let' cannot be the final code element in a block. Consider giving this block an explicit result.
-
-neg75.fsx(154,24,154,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
-neg75.fsx(154,24,154,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
-neg75.fsx(155,24,155,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
 neg75.fsx(155,24,155,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
 
 neg75.fsx(153,24,153,27): parse error FS0588: The block following this 'let' is unfinished. Every code block is an expression and must have a result. 'let' cannot be the final code element in a block. Consider giving this block an explicit result.
diff --git a/tests/fsharp/typecheck/sigs/neg76.bsl b/tests/fsharp/typecheck/sigs/neg76.bsl
index e5d4673dfc2..39f469708d1 100644
--- a/tests/fsharp/typecheck/sigs/neg76.bsl
+++ b/tests/fsharp/typecheck/sigs/neg76.bsl
@@ -1,10 +1,6 @@
 
 neg76.fsx(154,24,154,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
 
-neg76.fsx(154,24,154,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
-neg76.fsx(155,24,155,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
 neg76.fsx(155,24,155,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
 
 neg76.fsx(153,24,153,27): parse error FS0588: The block following this 'let' is unfinished. Every code block is an expression and must have a result. 'let' cannot be the final code element in a block. Consider giving this block an explicit result.
diff --git a/tests/fsharp/typecheck/sigs/neg76.vsbsl b/tests/fsharp/typecheck/sigs/neg76.vsbsl
index b7e157d83f6..39f469708d1 100644
--- a/tests/fsharp/typecheck/sigs/neg76.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg76.vsbsl
@@ -1,20 +1,6 @@
 
 neg76.fsx(154,24,154,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
 
-neg76.fsx(154,24,154,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
-neg76.fsx(155,24,155,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
-neg76.fsx(155,24,155,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
-neg76.fsx(153,24,153,27): parse error FS0588: The block following this 'let' is unfinished. Every code block is an expression and must have a result. 'let' cannot be the final code element in a block. Consider giving this block an explicit result.
-
-neg76.fsx(154,24,154,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
-neg76.fsx(154,24,154,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
-neg76.fsx(155,24,155,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
-
 neg76.fsx(155,24,155,27): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this token further or using standard formatting conventions.
 
 neg76.fsx(153,24,153,27): parse error FS0588: The block following this 'let' is unfinished. Every code block is an expression and must have a result. 'let' cannot be the final code element in a block. Consider giving this block an explicit result.
diff --git a/tests/fsharp/typecheck/sigs/neg77.bsl b/tests/fsharp/typecheck/sigs/neg77.bsl
index 922e6b66950..2214f281bae 100644
--- a/tests/fsharp/typecheck/sigs/neg77.bsl
+++ b/tests/fsharp/typecheck/sigs/neg77.bsl
@@ -1,6 +1,4 @@
 
 neg77.fsx(134,15,134,16): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (133:19). Try indenting this token further or using standard formatting conventions.
 
-neg77.fsx(134,15,134,16): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (133:19). Try indenting this token further or using standard formatting conventions.
-
 neg77.fsx(134,15,134,16): parse error FS0010: Unexpected symbol '|' in expression
diff --git a/tests/fsharp/typecheck/sigs/neg77.vsbsl b/tests/fsharp/typecheck/sigs/neg77.vsbsl
index 44832298057..b98c2358cb4 100644
--- a/tests/fsharp/typecheck/sigs/neg77.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg77.vsbsl
@@ -1,14 +1,6 @@
 
 neg77.fsx(134,15,134,16): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (133:19). Try indenting this token further or using standard formatting conventions.
 
-neg77.fsx(134,15,134,16): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (133:19). Try indenting this token further or using standard formatting conventions.
-
-neg77.fsx(134,15,134,16): parse error FS0010: Unexpected symbol '|' in expression
-
-neg77.fsx(134,15,134,16): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (133:19). Try indenting this token further or using standard formatting conventions.
-
-neg77.fsx(134,15,134,16): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (133:19). Try indenting this token further or using standard formatting conventions.
-
 neg77.fsx(134,15,134,16): parse error FS0010: Unexpected symbol '|' in expression
 
 neg77.fsx(153,75,153,79): typecheck error FS0001: The type 'Planet * 'a' is not compatible with the type 'Planet'
diff --git a/tests/fsharp/typecheck/sigs/neg79.vsbsl b/tests/fsharp/typecheck/sigs/neg79.vsbsl
index 5527cabeabb..b5599e27953 100644
--- a/tests/fsharp/typecheck/sigs/neg79.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg79.vsbsl
@@ -1,4 +1,2 @@
 
 neg79.fsx(31,32,31,33): parse error FS0010: Unexpected symbol ')' in if/then/else expression
-
-neg79.fsx(31,32,31,33): parse error FS0010: Unexpected symbol ')' in if/then/else expression
diff --git a/tests/fsharp/typecheck/sigs/neg80.vsbsl b/tests/fsharp/typecheck/sigs/neg80.vsbsl
index 63aba7d33db..86e8d40b6f4 100644
--- a/tests/fsharp/typecheck/sigs/neg80.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg80.vsbsl
@@ -1,4 +1,2 @@
 
 neg80.fsx(79,5,79,6): parse error FS0010: Unexpected symbol '|' in pattern matching
-
-neg80.fsx(79,5,79,6): parse error FS0010: Unexpected symbol '|' in pattern matching
diff --git a/tests/fsharp/typecheck/sigs/neg81.bsl b/tests/fsharp/typecheck/sigs/neg81.bsl
index fae282eb3e2..1f4cb33c987 100644
--- a/tests/fsharp/typecheck/sigs/neg81.bsl
+++ b/tests/fsharp/typecheck/sigs/neg81.bsl
@@ -1,8 +1,6 @@
 
 neg81.fsx(8,1,8,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (6:5). Try indenting this token further or using standard formatting conventions.
 
-neg81.fsx(8,1,8,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (6:5). Try indenting this token further or using standard formatting conventions.
-
 neg81.fsx(8,1,8,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (5:1). Try indenting this token further or using standard formatting conventions.
 
 neg81.fsx(6,6,6,7): parse error FS3156: Unexpected token '+' or incomplete expression
diff --git a/tests/fsharp/typecheck/sigs/neg81.vsbsl b/tests/fsharp/typecheck/sigs/neg81.vsbsl
index e7f03277d2b..1f4cb33c987 100644
--- a/tests/fsharp/typecheck/sigs/neg81.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg81.vsbsl
@@ -1,22 +1,6 @@
 
 neg81.fsx(8,1,8,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (6:5). Try indenting this token further or using standard formatting conventions.
 
-neg81.fsx(8,1,8,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (6:5). Try indenting this token further or using standard formatting conventions.
-
-neg81.fsx(8,1,8,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (5:1). Try indenting this token further or using standard formatting conventions.
-
-neg81.fsx(6,6,6,7): parse error FS3156: Unexpected token '+' or incomplete expression
-
-neg81.fsx(8,1,8,5): parse error FS0010: Unexpected keyword 'type' in binding. Expected incomplete structured construct at or before this point or other token.
-
-neg81.fsx(5,1,5,4): parse error FS3118: Incomplete value or function definition. If this is in an expression, the body of the expression must be indented to the same column as the 'let' keyword.
-
-neg81.fsx(10,1,10,1): parse error FS0010: Incomplete structured construct at or before this point in definition. Expected incomplete structured construct at or before this point or other token.
-
-neg81.fsx(8,1,8,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (6:5). Try indenting this token further or using standard formatting conventions.
-
-neg81.fsx(8,1,8,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (6:5). Try indenting this token further or using standard formatting conventions.
-
 neg81.fsx(8,1,8,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (5:1). Try indenting this token further or using standard formatting conventions.
 
 neg81.fsx(6,6,6,7): parse error FS3156: Unexpected token '+' or incomplete expression
diff --git a/tests/fsharp/typecheck/sigs/neg82.vsbsl b/tests/fsharp/typecheck/sigs/neg82.vsbsl
index 424ccedeb36..ec111d16e3d 100644
--- a/tests/fsharp/typecheck/sigs/neg82.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg82.vsbsl
@@ -19,24 +19,4 @@ neg82.fsx(102,1,102,4): parse error FS0058: Possible incorrect indentation: this
 
 neg82.fsx(138,1,138,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (102:1). Try indenting this token further or using standard formatting conventions.
 
-neg82.fsx(84,5,84,6): parse error FS0010: Unexpected symbol '|' in expression
-
-neg82.fsx(88,1,88,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (81:9). Try indenting this token further or using standard formatting conventions.
-
-neg82.fsx(90,5,90,8): parse error FS0010: Incomplete structured construct at or before this point in expression. Expected incomplete structured construct at or before this point or other token.
-
-neg82.fsx(95,1,95,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (88:1). Try indenting this token further or using standard formatting conventions.
-
-neg82.fsx(95,1,95,4): parse error FS0010: Unexpected keyword 'let' or 'use' in implementation file
-
-neg82.fsx(96,1,96,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (95:1). Try indenting this token further or using standard formatting conventions.
-
-neg82.fsx(97,1,97,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:1). Try indenting this token further or using standard formatting conventions.
-
-neg82.fsx(100,1,100,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (97:1). Try indenting this token further or using standard formatting conventions.
-
-neg82.fsx(102,1,102,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (100:1). Try indenting this token further or using standard formatting conventions.
-
-neg82.fsx(138,1,138,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (102:1). Try indenting this token further or using standard formatting conventions.
-
 neg82.fsx(93,5,93,7): typecheck error FS0039: The value, namespace, type or module 'sb' is not defined.
diff --git a/tests/fsharp/typecheck/sigs/neg83.bsl b/tests/fsharp/typecheck/sigs/neg83.bsl
index 3390f9cd883..30ff9979141 100644
--- a/tests/fsharp/typecheck/sigs/neg83.bsl
+++ b/tests/fsharp/typecheck/sigs/neg83.bsl
@@ -5,6 +5,4 @@ neg83.fsx(13,1,13,2): parse error FS0058: Possible incorrect indentation: this t
 
 neg83.fsx(13,2,13,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (4:4). Try indenting this token further or using standard formatting conventions.
 
-neg83.fsx(13,2,13,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (4:4). Try indenting this token further or using standard formatting conventions.
-
 neg83.fsx(16,1,16,1): parse error FS0010: Incomplete structured construct at or before this point in expression
diff --git a/tests/fsharp/typecheck/sigs/neg83.vsbsl b/tests/fsharp/typecheck/sigs/neg83.vsbsl
index 24cd7e0cfb5..30ff9979141 100644
--- a/tests/fsharp/typecheck/sigs/neg83.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg83.vsbsl
@@ -5,16 +5,4 @@ neg83.fsx(13,1,13,2): parse error FS0058: Possible incorrect indentation: this t
 
 neg83.fsx(13,2,13,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (4:4). Try indenting this token further or using standard formatting conventions.
 
-neg83.fsx(13,2,13,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (4:4). Try indenting this token further or using standard formatting conventions.
-
-neg83.fsx(16,1,16,1): parse error FS0010: Incomplete structured construct at or before this point in expression
-
-neg83.fsx(10,5,10,6): parse error FS0010: Unexpected symbol '|' in expression
-
-neg83.fsx(13,1,13,2): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (4:4). Try indenting this token further or using standard formatting conventions.
-
-neg83.fsx(13,2,13,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (4:4). Try indenting this token further or using standard formatting conventions.
-
-neg83.fsx(13,2,13,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (4:4). Try indenting this token further or using standard formatting conventions.
-
 neg83.fsx(16,1,16,1): parse error FS0010: Incomplete structured construct at or before this point in expression
diff --git a/tests/fsharp/typecheck/sigs/neg84.vsbsl b/tests/fsharp/typecheck/sigs/neg84.vsbsl
index 2b7a0c06bee..6d4db3adec9 100644
--- a/tests/fsharp/typecheck/sigs/neg84.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg84.vsbsl
@@ -1,4 +1,2 @@
 
 neg84.fsx(11,1,11,1): parse error FS0010: Incomplete structured construct at or before this point in expression
-
-neg84.fsx(11,1,11,1): parse error FS0010: Incomplete structured construct at or before this point in expression
diff --git a/tests/fsharp/typecheck/sigs/neg86.vsbsl b/tests/fsharp/typecheck/sigs/neg86.vsbsl
index 638377e4bf9..667ca721ae3 100644
--- a/tests/fsharp/typecheck/sigs/neg86.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg86.vsbsl
@@ -1,8 +1,6 @@
 
 neg86.fsx(18,20,18,22): parse error FS3156: Unexpected token 'in' or incomplete expression
 
-neg86.fsx(18,20,18,22): parse error FS3156: Unexpected token 'in' or incomplete expression
-
 neg86.fsx(4,21,4,23): typecheck error FS3156: Unexpected token 'in' or incomplete expression
 
 neg86.fsx(8,13,8,17): typecheck error FS3096: 'join' must be followed by a variable name. Usage: join var in collection on (outerKey = innerKey). Note that parentheses are required after 'on'.
diff --git a/tests/fsharp/typecheck/sigs/neg89.bsl b/tests/fsharp/typecheck/sigs/neg89.bsl
index 0f81ef3b09b..77ef120086e 100644
--- a/tests/fsharp/typecheck/sigs/neg89.bsl
+++ b/tests/fsharp/typecheck/sigs/neg89.bsl
@@ -1,44 +1,10 @@
 
 neg89.fsx(2,10,2,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
 
-neg89.fsx(2,10,2,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(3,9,3,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(3,9,3,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(3,9,3,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
 neg89.fsx(3,9,3,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
 
 neg89.fsx(6,10,6,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
 
-neg89.fsx(6,10,6,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(6,10,6,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(6,10,6,11): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(7,9,7,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(7,9,7,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(7,9,7,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
 neg89.fsx(7,9,7,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
 
 neg89.fsx(8,9,8,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(8,9,8,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(8,9,8,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(8,9,8,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(8,9,8,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(8,9,8,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(8,9,8,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
-
-neg89.fsx(8,9,8,10): typecheck error FS0953: This type definition involves an immediate cyclic reference through an abbreviation
diff --git a/tests/fsharp/typecheck/sigs/neg90.bsl b/tests/fsharp/typecheck/sigs/neg90.bsl
index 5f8f380d3ef..d04c6f2b059 100644
--- a/tests/fsharp/typecheck/sigs/neg90.bsl
+++ b/tests/fsharp/typecheck/sigs/neg90.bsl
@@ -3,8 +3,6 @@ neg90.fs(4,9,4,12): typecheck error FS0001: A generic construct requires that th
 
 neg90.fs(7,22,7,25): typecheck error FS0039: The type 'foo' is not defined.
 
-neg90.fs(7,22,7,25): typecheck error FS0039: The type 'foo' is not defined.
-
 neg90.fs(16,9,16,21): typecheck error FS0035: This construct is deprecated: The union type for union case 'Member' was defined with the RequireQualifiedAccessAttribute. Include the name of the union type ('DU') in the name you are using.
 
 neg90.fs(28,9,28,41): typecheck error FS0035: This construct is deprecated: The record type for the record field 'Field1' was defined with the RequireQualifiedAccessAttribute. Include the name of the record type ('Record1') in the name you are using.
diff --git a/tests/fsharp/typecheck/sigs/neg95.bsl b/tests/fsharp/typecheck/sigs/neg95.bsl
index ba9ceefb4e6..daa32cb1a99 100644
--- a/tests/fsharp/typecheck/sigs/neg95.bsl
+++ b/tests/fsharp/typecheck/sigs/neg95.bsl
@@ -13,4 +13,4 @@ neg95.fs(39,7,39,18): typecheck error FS3200: In a recursive declaration group,
 
 neg95.fs(45,10,45,22): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
 
-neg95.fs(52,10,52,21): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
\ No newline at end of file
+neg95.fs(52,10,52,21): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
diff --git a/tests/fsharp/typecheck/sigs/neg96.bsl b/tests/fsharp/typecheck/sigs/neg96.bsl
index cd87ec8144c..9a6e2882974 100644
--- a/tests/fsharp/typecheck/sigs/neg96.bsl
+++ b/tests/fsharp/typecheck/sigs/neg96.bsl
@@ -2,5 +2,3 @@
 neg96.fs(11,9,11,21): typecheck error FS1133: No constructors are available for the type 'StructRecord'
 
 neg96.fs(18,10,18,11): typecheck error FS0039: The type 'X' is not defined.
-
-neg96.fs(18,10,18,11): typecheck error FS0039: The type 'X' is not defined.
diff --git a/tests/fsharp/typecheck/sigs/neg_byref_11.bsl b/tests/fsharp/typecheck/sigs/neg_byref_11.bsl
index 6c71b1f88a1..c3f35c64bf8 100644
--- a/tests/fsharp/typecheck/sigs/neg_byref_11.bsl
+++ b/tests/fsharp/typecheck/sigs/neg_byref_11.bsl
@@ -2,9 +2,3 @@
 neg_byref_11.fs(3,13,3,14): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
 
 neg_byref_11.fs(3,6,3,8): typecheck error FS0437: A type would store a byref typed value. This is not permitted by Common IL.
-
-neg_byref_11.fs(3,13,3,14): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_11.fs(3,13,3,14): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_11.fs(3,13,3,14): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
diff --git a/tests/fsharp/typecheck/sigs/neg_byref_12.bsl b/tests/fsharp/typecheck/sigs/neg_byref_12.bsl
index c3ecf36b111..3bd33b8bc5e 100644
--- a/tests/fsharp/typecheck/sigs/neg_byref_12.bsl
+++ b/tests/fsharp/typecheck/sigs/neg_byref_12.bsl
@@ -4,7 +4,3 @@ neg_byref_12.fs(3,21,3,31): typecheck error FS0412: A type instantiation involve
 neg_byref_12.fs(3,6,3,8): typecheck error FS0437: A type would store a byref typed value. This is not permitted by Common IL.
 
 neg_byref_12.fs(3,11,3,17): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_12.fs(3,11,3,17): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_12.fs(3,11,3,17): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
diff --git a/tests/fsharp/typecheck/sigs/neg_byref_14.bsl b/tests/fsharp/typecheck/sigs/neg_byref_14.bsl
index 71ad2babfbc..90ae023f45f 100644
--- a/tests/fsharp/typecheck/sigs/neg_byref_14.bsl
+++ b/tests/fsharp/typecheck/sigs/neg_byref_14.bsl
@@ -4,7 +4,3 @@ neg_byref_14.fs(3,29,3,39): typecheck error FS0412: A type instantiation involve
 neg_byref_14.fs(3,11,3,25): typecheck error FS0437: A type would store a byref typed value. This is not permitted by Common IL.
 
 neg_byref_14.fs(3,11,3,25): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_14.fs(3,11,3,25): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_14.fs(3,11,3,25): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
diff --git a/tests/fsharp/typecheck/sigs/neg_byref_16.bsl b/tests/fsharp/typecheck/sigs/neg_byref_16.bsl
index d7964e54120..2843736a8f3 100644
--- a/tests/fsharp/typecheck/sigs/neg_byref_16.bsl
+++ b/tests/fsharp/typecheck/sigs/neg_byref_16.bsl
@@ -3,6 +3,4 @@ neg_byref_16.fs(3,5,3,6): typecheck error FS3301: The function or method has an
 
 neg_byref_16.fs(3,33,3,42): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
 
-neg_byref_16.fs(3,33,3,42): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
 neg_byref_16.fs(3,40,3,41): typecheck error FS0421: The address of the variable 'a' cannot be used at this point
diff --git a/tests/fsharp/typecheck/sigs/neg_byref_20.bsl b/tests/fsharp/typecheck/sigs/neg_byref_20.bsl
index 408b36c3df4..eecb7fcc8f5 100644
--- a/tests/fsharp/typecheck/sigs/neg_byref_20.bsl
+++ b/tests/fsharp/typecheck/sigs/neg_byref_20.bsl
@@ -1,4 +1,2 @@
 
 neg_byref_20.fs(2,2,2,21): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_20.fs(2,2,2,21): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
diff --git a/tests/fsharp/typecheck/sigs/neg_byref_22.bsl b/tests/fsharp/typecheck/sigs/neg_byref_22.bsl
index 7c5e93d3151..a4a9bad818a 100644
--- a/tests/fsharp/typecheck/sigs/neg_byref_22.bsl
+++ b/tests/fsharp/typecheck/sigs/neg_byref_22.bsl
@@ -5,8 +5,3 @@ neg_byref_22.fs(3,16,3,20): typecheck error FS0001: This expression was expected
     'byref'    
 but here has type
     'int'    
-
-neg_byref_22.fs(3,16,3,20): typecheck error FS0001: This expression was expected to have type
-    'byref'    
-but here has type
-    'int'    
diff --git a/tests/fsharp/typecheck/sigs/neg_byref_3.bsl b/tests/fsharp/typecheck/sigs/neg_byref_3.bsl
index 48fb07c7f7e..05043743640 100644
--- a/tests/fsharp/typecheck/sigs/neg_byref_3.bsl
+++ b/tests/fsharp/typecheck/sigs/neg_byref_3.bsl
@@ -5,10 +5,6 @@ neg_byref_3.fs(2,5,2,8): typecheck error FS0412: A type instantiation involves a
 
 neg_byref_3.fs(2,11,2,22): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
 
-neg_byref_3.fs(2,11,2,22): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
 neg_byref_3.fs(3,5,3,6): typecheck error FS3301: The function or method has an invalid return type '(byref list -> int)'. This is not permitted by the rules of Common IL.
 
 neg_byref_3.fs(3,11,3,22): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_3.fs(3,11,3,22): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
diff --git a/tests/fsharp/typecheck/sigs/neg_byref_7.bsl b/tests/fsharp/typecheck/sigs/neg_byref_7.bsl
index cbe7789b3a1..89a797bea13 100644
--- a/tests/fsharp/typecheck/sigs/neg_byref_7.bsl
+++ b/tests/fsharp/typecheck/sigs/neg_byref_7.bsl
@@ -1,10 +1,6 @@
 
 neg_byref_7.fs(2,31,2,35): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
 
-neg_byref_7.fs(2,31,2,35): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_7.fs(2,38,2,43): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
 neg_byref_7.fs(2,38,2,43): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
 
 neg_byref_7.fs(2,39,2,40): typecheck error FS0418: The byref typed value 'v' cannot be used at this point
@@ -13,12 +9,4 @@ neg_byref_7.fs(2,42,2,43): typecheck error FS0418: The byref typed value 'v' can
 
 neg_byref_7.fs(2,47,2,60): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
 
-neg_byref_7.fs(2,47,2,60): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_7.fs(2,47,2,53): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_7.fs(2,47,2,53): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_7.fs(2,47,2,53): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
 neg_byref_7.fs(2,47,2,53): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
diff --git a/tests/fsharp/typecheck/sigs/neg_byref_8.bsl b/tests/fsharp/typecheck/sigs/neg_byref_8.bsl
index d39ae5771d1..11830fd6b92 100644
--- a/tests/fsharp/typecheck/sigs/neg_byref_8.bsl
+++ b/tests/fsharp/typecheck/sigs/neg_byref_8.bsl
@@ -1,10 +1,6 @@
 
 neg_byref_8.fs(2,31,2,35): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
 
-neg_byref_8.fs(2,31,2,35): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_8.fs(2,38,2,43): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
 neg_byref_8.fs(2,38,2,43): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
 
 neg_byref_8.fs(2,39,2,40): typecheck error FS0418: The byref typed value 'v' cannot be used at this point
@@ -13,12 +9,4 @@ neg_byref_8.fs(2,42,2,43): typecheck error FS0418: The byref typed value 'v' can
 
 neg_byref_8.fs(2,47,2,60): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
 
-neg_byref_8.fs(2,47,2,60): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_8.fs(2,47,2,53): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_8.fs(2,47,2,53): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
-neg_byref_8.fs(2,47,2,53): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
-
 neg_byref_8.fs(2,47,2,53): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.

From 382354ae01f13e5ddde72d233327453268bb9782 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Thu, 25 May 2023 13:33:04 +0100
Subject: [PATCH 11/59] don't overwrite baselines

---
 tests/FSharp.Test.Utilities/Compiler.fs | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs
index b060a6f16ba..fd1a679babe 100644
--- a/tests/FSharp.Test.Utilities/Compiler.fs
+++ b/tests/FSharp.Test.Utilities/Compiler.fs
@@ -1448,11 +1448,11 @@ module rec Compiler =
                 let expectedContent = File.ReadAllText(path) |> normalizeNewLines
                 let actualErrors = renderToString result                
 
-                //match Environment.GetEnvironmentVariable("TEST_UPDATE_BSL") with
-                //| null -> ()
-                //| _ when expectedContent = actualErrors -> ()
-                //| _ -> File.WriteAllText(path, actualErrors)
-                File.WriteAllText(path, actualErrors)
+                match Environment.GetEnvironmentVariable("TEST_UPDATE_BSL") with
+                | null -> ()
+                | _ when expectedContent = actualErrors -> ()
+                | _ -> File.WriteAllText(path, actualErrors)
+                //File.WriteAllText(path, actualErrors)
 
                 match Assert.shouldBeSameMultilineStringSets expectedContent actualErrors with
                 | None -> () 

From 1685da8a0445ed284b4f58483388b81274cd4606 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Thu, 25 May 2023 14:43:17 +0100
Subject: [PATCH 12/59] fix some test failures

---
 src/Compiler/Checking/CheckExpressions.fs    | 4 ++++
 src/Compiler/Checking/MethodCalls.fs         | 6 +++++-
 src/Compiler/Checking/PostInferenceChecks.fs | 6 +++++-
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs
index f53b7c07c3c..1aacafda3ca 100644
--- a/src/Compiler/Checking/CheckExpressions.fs
+++ b/src/Compiler/Checking/CheckExpressions.fs
@@ -4747,6 +4747,10 @@ and TcStaticConstantParameter (cenv: cenv) (env: TcEnv) tpenv kind (StripParenTy
         | _ -> ()
 
     match v with
+    | SynType.StaticConstantNull _ when typeEquiv g g.string_ty kind ->
+        record(g.string_ty)
+        null, tpenv
+
     | SynType.StaticConstant(sc, _) ->
         let v =
             match sc with
diff --git a/src/Compiler/Checking/MethodCalls.fs b/src/Compiler/Checking/MethodCalls.fs
index 322aa43c53a..0319027a5be 100644
--- a/src/Compiler/Checking/MethodCalls.fs
+++ b/src/Compiler/Checking/MethodCalls.fs
@@ -1184,8 +1184,12 @@ let BuildMethodCall tcVal g amap isMutable m isProp minfo valUseFlags minst objA
         // Build a 'call' to a struct default constructor 
         | DefaultStructCtor (g, ty) -> 
             if g.langFeatureNullness && g.checkNullness then
-                if not (TypeHasDefaultValueNew g m ty) then 
+                if not (TypeHasDefaultValue g m ty) then 
                     errorR(Error(FSComp.SR.tcDefaultStructConstructorCall(), m))
+                // If the condition is detected because of a variation in logic introduced because
+                // of nullness checking, then only a warning is emitted.
+                elif not (TypeHasDefaultValueNew g m ty) then 
+                    warning(Error(FSComp.SR.tcDefaultStructConstructorCall(), m))
             else
                 if not (TypeHasDefaultValue g m ty) then 
                     errorR(Error(FSComp.SR.tcDefaultStructConstructorCall(), m))
diff --git a/src/Compiler/Checking/PostInferenceChecks.fs b/src/Compiler/Checking/PostInferenceChecks.fs
index cf18598d158..3f5aff9533b 100644
--- a/src/Compiler/Checking/PostInferenceChecks.fs
+++ b/src/Compiler/Checking/PostInferenceChecks.fs
@@ -2540,8 +2540,12 @@ let CheckEntityDefn cenv env (tycon: Entity) =
                 let zeroInitUnsafe = TryFindFSharpBoolAttribute g g.attrib_DefaultValueAttribute f.FieldAttribs
                 if zeroInitUnsafe = Some true then
                     let ty = f.FormalType
-                    if not (TypeHasDefaultValueNew g m ty) then 
+                    // If the condition is detected because of a variation in logic introduced because
+                    // of nullness checking, then only a warning is emitted.
+                    if not (TypeHasDefaultValue g m ty) then 
                         errorR(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValue(), m))
+                    elif not (TypeHasDefaultValueNew g m ty) then 
+                        warning(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValue(), m))
 
         // These are the old rules (not g.langFeatureNullness or not g.checkNullness), mistakenly only applied to structs
         elif tycon.IsStructOrEnumTycon then 

From 11e88c8887274a5673037a6f86e11c114d9ec05b Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Thu, 25 May 2023 15:23:00 +0100
Subject: [PATCH 13/59] skip warnings

---
 src/Compiler/Checking/CheckExpressions.fs | 4 ----
 tests/adhoc/nullness/nullness.fsproj      | 1 +
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs
index 1aacafda3ca..f53b7c07c3c 100644
--- a/src/Compiler/Checking/CheckExpressions.fs
+++ b/src/Compiler/Checking/CheckExpressions.fs
@@ -4747,10 +4747,6 @@ and TcStaticConstantParameter (cenv: cenv) (env: TcEnv) tpenv kind (StripParenTy
         | _ -> ()
 
     match v with
-    | SynType.StaticConstantNull _ when typeEquiv g g.string_ty kind ->
-        record(g.string_ty)
-        null, tpenv
-
     | SynType.StaticConstant(sc, _) ->
         let v =
             match sc with
diff --git a/tests/adhoc/nullness/nullness.fsproj b/tests/adhoc/nullness/nullness.fsproj
index 1c12b9cec98..b8f06c10197 100644
--- a/tests/adhoc/nullness/nullness.fsproj
+++ b/tests/adhoc/nullness/nullness.fsproj
@@ -12,6 +12,7 @@
     $(OtherFlags) /checknulls /sig:out.fsi 
     
     $(OtherFlags) --nowarn:3261
+    $(OtherFlags) --nowarn:444
   
 
   

From ee80415262b43d8b2eb6819045e0f79dc3962b96 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Thu, 25 May 2023 16:42:28 +0100
Subject: [PATCH 14/59] skip warnings

---
 ...vice.SurfaceArea.netstandard20.release.bsl | 33 ++++++++++++++++++-
 tests/adhoc/nullness/enabled/negative.fs      |  4 +++
 tests/adhoc/nullness/enabled/positive.fs      |  7 ----
 3 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl
index 0faf9512f36..bb8fe8eae38 100644
--- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl
+++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl
@@ -11341,4 +11341,35 @@ FSharp.Compiler.Xml.XmlDoc: System.String GetXmlText()
 FSharp.Compiler.Xml.XmlDoc: System.String[] GetElaboratedXmlLines()
 FSharp.Compiler.Xml.XmlDoc: System.String[] UnprocessedLines
 FSharp.Compiler.Xml.XmlDoc: System.String[] get_UnprocessedLines()
-FSharp.Compiler.Xml.XmlDoc: Void .ctor(System.String[], FSharp.Compiler.Text.Range)
\ No newline at end of file
+FSharp.Compiler.Xml.XmlDoc: Void .ctor(System.String[], FSharp.Compiler.Text.Range)
+FSharp.Compiler.Symbols.FSharpType: Boolean HasNullAnnotation
+FSharp.Compiler.Symbols.FSharpType: Boolean IsNullAmbivalent
+FSharp.Compiler.Symbols.FSharpType: Boolean get_HasNullAnnotation()
+FSharp.Compiler.Symbols.FSharpType: Boolean get_IsNullAmbivalent()
+FSharp.Compiler.Syntax.SynType+StaticConstantNull: FSharp.Compiler.Text.Range get_range()
+FSharp.Compiler.Syntax.SynType+StaticConstantNull: FSharp.Compiler.Text.Range range
+FSharp.Compiler.Syntax.SynType+Tags: Int32 StaticConstantNull
+FSharp.Compiler.Syntax.SynType+Tags: Int32 WithNull
+FSharp.Compiler.Syntax.SynType+WithNull: Boolean ambivalent
+FSharp.Compiler.Syntax.SynType+WithNull: Boolean get_ambivalent()
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Syntax.SynType get_innerType()
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Syntax.SynType innerType
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Text.Range get_range()
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Text.Range range
+FSharp.Compiler.Syntax.SynType: Boolean IsStaticConstantNull
+FSharp.Compiler.Syntax.SynType: Boolean IsWithNull
+FSharp.Compiler.Syntax.SynType: Boolean get_IsStaticConstantNull()
+FSharp.Compiler.Syntax.SynType: Boolean get_IsWithNull()
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewStaticConstantNull(FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewWithNull(FSharp.Compiler.Syntax.SynType, Boolean, FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+StaticConstantNull
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+WithNull
+FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparNotSupportsNull
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Syntax.SynTypar genericName
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Syntax.SynTypar get_genericName()
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Text.Range get_range()
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Text.Range range
+FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparNotSupportsNull
+FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparNotSupportsNull()
+FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparNotSupportsNull(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull
\ No newline at end of file
diff --git a/tests/adhoc/nullness/enabled/negative.fs b/tests/adhoc/nullness/enabled/negative.fs
index d3509f2ab1d..d088a4e045a 100644
--- a/tests/adhoc/nullness/enabled/negative.fs
+++ b/tests/adhoc/nullness/enabled/negative.fs
@@ -43,6 +43,10 @@ module NullConstraintTests =
             []
             val mutable Whoops : int FSharp.Collections.List // expect an error if checknulls is on
 
+        type C4b =
+            []
+            val mutable Whoops : int FSharp.Collections.List __withnull // expect no warning
+
         type C5 =
             []
             val mutable Whoops : int * int // expect an error like previous F#
diff --git a/tests/adhoc/nullness/enabled/positive.fs b/tests/adhoc/nullness/enabled/positive.fs
index 76428ce8355..b4ecd9309f7 100644
--- a/tests/adhoc/nullness/enabled/positive.fs
+++ b/tests/adhoc/nullness/enabled/positive.fs
@@ -228,10 +228,3 @@ module DefaultValueTests =
             []
             val mutable Whoops : String __withnull // expect no warning
 
-        type C4b =
-            []
-            val mutable Whoops : int FSharp.Collections.List __withnull // expect no warning
-
-        type C7 =
-            []
-            val mutable Whoops : (int -> int) __withnull // expect no warning

From f0fc3bf2362a60d0e9156ad2043f6b5364c854cb Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Thu, 25 May 2023 17:38:36 +0100
Subject: [PATCH 15/59] fix warning logic

---
 src/Compiler/Checking/ConstraintSolver.fs    |  2 ++
 src/Compiler/Checking/MethodCalls.fs         | 13 +++++++------
 src/Compiler/Checking/PostInferenceChecks.fs |  9 +++++----
 tests/adhoc/nullness/enabled/negative.fs     |  8 --------
 tests/adhoc/nullness/enabled/positive.fs     |  7 +++++++
 5 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs
index 6495ef15655..a76c6bb1d11 100644
--- a/src/Compiler/Checking/ConstraintSolver.fs
+++ b/src/Compiler/Checking/ConstraintSolver.fs
@@ -2494,6 +2494,8 @@ and SolveTypeUseSupportsNull (csenv: ConstraintSolverEnv) ndeep m2 trace ty = tr
             | ValueSome tp ->
                 let nullness = nullnessOfTy g ty
                 match nullness.TryEvaluate() with
+                // NULLNESS TODO: This rule means turning on checkNullness changes type inference results for the cases
+                // mentioned in the comment above. THat's OK but needs to be documented in the RFC.
                 | ValueNone when not g.checkNullness ->
                     return! AddConstraint csenv ndeep m2 trace tp (TyparConstraint.SupportsNull m)
                 | ValueSome NullnessInfo.WithoutNull ->
diff --git a/src/Compiler/Checking/MethodCalls.fs b/src/Compiler/Checking/MethodCalls.fs
index 0319027a5be..2c3f9e82a6c 100644
--- a/src/Compiler/Checking/MethodCalls.fs
+++ b/src/Compiler/Checking/MethodCalls.fs
@@ -1184,12 +1184,13 @@ let BuildMethodCall tcVal g amap isMutable m isProp minfo valUseFlags minst objA
         // Build a 'call' to a struct default constructor 
         | DefaultStructCtor (g, ty) -> 
             if g.langFeatureNullness && g.checkNullness then
-                if not (TypeHasDefaultValue g m ty) then 
-                    errorR(Error(FSComp.SR.tcDefaultStructConstructorCall(), m))
-                // If the condition is detected because of a variation in logic introduced because
-                // of nullness checking, then only a warning is emitted.
-                elif not (TypeHasDefaultValueNew g m ty) then 
-                    warning(Error(FSComp.SR.tcDefaultStructConstructorCall(), m))
+                if not (TypeHasDefaultValueNew g m ty) then
+                    // If the condition is detected because of a variation in logic introduced because
+                    // of nullness checking, then only a warning is emitted.
+                    if not (TypeHasDefaultValue g m ty) then 
+                        errorR(Error(FSComp.SR.tcDefaultStructConstructorCall(), m))
+                    else
+                        warning(Error(FSComp.SR.tcDefaultStructConstructorCall(), m))
             else
                 if not (TypeHasDefaultValue g m ty) then 
                     errorR(Error(FSComp.SR.tcDefaultStructConstructorCall(), m))
diff --git a/src/Compiler/Checking/PostInferenceChecks.fs b/src/Compiler/Checking/PostInferenceChecks.fs
index 3f5aff9533b..32ed99523d7 100644
--- a/src/Compiler/Checking/PostInferenceChecks.fs
+++ b/src/Compiler/Checking/PostInferenceChecks.fs
@@ -2542,10 +2542,11 @@ let CheckEntityDefn cenv env (tycon: Entity) =
                     let ty = f.FormalType
                     // If the condition is detected because of a variation in logic introduced because
                     // of nullness checking, then only a warning is emitted.
-                    if not (TypeHasDefaultValue g m ty) then 
-                        errorR(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValue(), m))
-                    elif not (TypeHasDefaultValueNew g m ty) then 
-                        warning(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValue(), m))
+                    if not (TypeHasDefaultValueNew g m ty) then 
+                        if not (TypeHasDefaultValue g m ty) then 
+                            errorR(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValue(), m))
+                        else
+                            warning(Error(FSComp.SR.chkValueWithDefaultValueMustHaveDefaultValue(), m))
 
         // These are the old rules (not g.langFeatureNullness or not g.checkNullness), mistakenly only applied to structs
         elif tycon.IsStructOrEnumTycon then 
diff --git a/tests/adhoc/nullness/enabled/negative.fs b/tests/adhoc/nullness/enabled/negative.fs
index d088a4e045a..5722820e23e 100644
--- a/tests/adhoc/nullness/enabled/negative.fs
+++ b/tests/adhoc/nullness/enabled/negative.fs
@@ -43,10 +43,6 @@ module NullConstraintTests =
             []
             val mutable Whoops : int FSharp.Collections.List // expect an error if checknulls is on
 
-        type C4b =
-            []
-            val mutable Whoops : int FSharp.Collections.List __withnull // expect no warning
-
         type C5 =
             []
             val mutable Whoops : int * int // expect an error like previous F#
@@ -54,7 +50,3 @@ module NullConstraintTests =
         type C6 =
             []
             val mutable Whoops : int -> int // expect an error like previous F#
-
-        type C7 =
-            []
-            val mutable Whoops : (int -> int) __withnull // expect no warning
diff --git a/tests/adhoc/nullness/enabled/positive.fs b/tests/adhoc/nullness/enabled/positive.fs
index b4ecd9309f7..76428ce8355 100644
--- a/tests/adhoc/nullness/enabled/positive.fs
+++ b/tests/adhoc/nullness/enabled/positive.fs
@@ -228,3 +228,10 @@ module DefaultValueTests =
             []
             val mutable Whoops : String __withnull // expect no warning
 
+        type C4b =
+            []
+            val mutable Whoops : int FSharp.Collections.List __withnull // expect no warning
+
+        type C7 =
+            []
+            val mutable Whoops : (int -> int) __withnull // expect no warning

From e4999fd6bb6223be4b6a8150cf2a7d492b1f8fa8 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Thu, 25 May 2023 20:37:24 +0100
Subject: [PATCH 16/59] fix tests

---
 tests/AheadOfTime/Trimming/check.ps1                            | 2 +-
 .../Source/CompilerOptions/fsi/help/help40-nologo.437.1033.bsl  | 2 ++
 .../Source/CompilerOptions/fsi/help/help40.437.1033.bsl         | 2 ++
 3 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index d8151aef14e..71e29881fa3 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -37,7 +37,7 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) {
 
 
 # Check net7.0 trimmed assemblies
-CheckTrim -root "SelfContained_Trimming_Test" -tfm "net7.0" -outputfile "FSharp.Core.dll" -expected_len 287744
+CheckTrim -root "SelfContained_Trimming_Test" -tfm "net7.0" -outputfile "FSharp.Core.dll" -expected_len (If ($compressAllMetadata) {300544} Else {288768})
 
 # Check net472 trimmed assemblies -- net472 doesn't actually trim, this just checks that everything is usable when published trimmed
 CheckTrim -root "SelfContained_Trimming_Test" -tfm "net472" -outputfile "FSharp.Core.dll" -expected_len -1
diff --git a/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40-nologo.437.1033.bsl b/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40-nologo.437.1033.bsl
index b0d97ddcd12..a0688acd92d 100644
--- a/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40-nologo.437.1033.bsl
+++ b/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40-nologo.437.1033.bsl
@@ -49,6 +49,8 @@ Usage: fsiAnyCpu  [script.fsx []]
 --nowarn:                      Disable specific warning messages
 --warnon:                      Enable specific warnings that may be
                                          off by default
+--checknulls[+|-]                        Enable nullness declarations and
+                                         checks
 --consolecolors[+|-]                     Output warning and error messages in
                                          color
 
diff --git a/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40.437.1033.bsl b/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40.437.1033.bsl
index e95a139b5fb..165d37df496 100644
--- a/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40.437.1033.bsl
+++ b/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40.437.1033.bsl
@@ -51,6 +51,8 @@ Usage: fsiAnyCpu  [script.fsx []]
 --nowarn:                      Disable specific warning messages
 --warnon:                      Enable specific warnings that may be
                                          off by default
+--checknulls[+|-]                        Enable nullness declarations and
+                                         checks
 --consolecolors[+|-]                     Output warning and error messages in
                                          color
 

From 0f83cd254fff77c105fa6e685b0b1646f3bca893 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Thu, 25 May 2023 21:07:20 +0100
Subject: [PATCH 17/59] fix sizes

---
 tests/AheadOfTime/Trimming/check.ps1 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index 71e29881fa3..db02e481491 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -47,4 +47,4 @@ CheckTrim -root "SelfContained_Trimming_Test" -tfm "net472" -outputfile "FSharp.
 CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net472" -outputfile "StaticLinkedFSharpCore_Trimming_Test.exe" -expected_len -1
 
 # Check net7.0 trimmed assemblies
-CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net7.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 8820736
+CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net7.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len (If ($compressAllMetadata) {8821760} Else {8821760})

From d3a7bc7504c1c63a1593ee44c4af7b451bf8066f Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Fri, 26 May 2023 14:11:49 +0100
Subject: [PATCH 18/59] fix build

---
 FSharp.Profiles.props                      |  3 ++-
 src/Compiler/Checking/ConstraintSolver.fs  | 28 ++++++++++---------
 src/Compiler/Checking/NicePrint.fs         | 23 ++++++++++++----
 src/Compiler/Driver/CompilerDiagnostics.fs |  9 +++++++
 src/Compiler/Interactive/fsi.fs            |  8 +++---
 src/Compiler/Symbols/SymbolHelpers.fs      |  2 +-
 src/Compiler/TypedTree/TcGlobals.fs        |  5 ++++
 src/Compiler/TypedTree/TypedTreeOps.fs     | 31 ++++++++++++++++------
 src/Compiler/TypedTree/TypedTreeOps.fsi    |  2 +-
 src/Compiler/Utilities/illib.fs            | 10 +++----
 10 files changed, 82 insertions(+), 39 deletions(-)

diff --git a/FSharp.Profiles.props b/FSharp.Profiles.props
index d477f570f34..27aaa965d68 100644
--- a/FSharp.Profiles.props
+++ b/FSharp.Profiles.props
@@ -12,7 +12,8 @@
   
 
   
-    BUILDING_WITH_LKG;NO_NULLCHECKING_LIB_SUPPORT;$(DefineConstants)
+    false
+    NO_CHECKNULLS;BUILDING_WITH_LKG;NO_NULLCHECKING_LIB_SUPPORT;$(DefineConstants)
     false
   
 
diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs
index a76c6bb1d11..7e1bd3b3f05 100644
--- a/src/Compiler/Checking/ConstraintSolver.fs
+++ b/src/Compiler/Checking/ConstraintSolver.fs
@@ -1294,19 +1294,19 @@ and SolveTypeEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTr
             )
 
     // Catch float<_>=float<1>, float32<_>=float32<1> and decimal<_>=decimal<1> 
-    | (_, TType_app (tc2, [ms2], nullness2)) when (tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms2])) ->
+    | (_, TType_app (tc2, [ms2], _)) when (tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms2])) ->
         SolveTypeEqualsType csenv ndeep m2 trace None (TType_measure Measure.One) ms2 ++ (fun () -> 
-           SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) nullness2
+           SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
         )
 
-    | (TType_app (tc1, [ms1], nullness1), _) when (tc1.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc1 [ms1])) ->
+    | (TType_app (tc1, [ms1], _), _) when (tc1.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc1 [ms1])) ->
         SolveTypeEqualsType csenv ndeep m2 trace None ms1 (TType_measure Measure.One) ++ (fun () -> 
-           SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 (nullnessOfTy g sty2)
+           SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
         )
 
-    | TType_app (tc1, l1, nullness1), TType_app (tc2, l2, nullness2) when tyconRefEq g tc1 tc2  ->
+    | TType_app (tc1, l1, _), TType_app (tc2, l2, _) when tyconRefEq g tc1 tc2  ->
         SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2 ++ (fun () -> 
-           SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullness2
+           SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
         )
 
     | TType_app _, TType_app _ ->
@@ -1429,14 +1429,14 @@ and SolveTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optional
         UnifyMeasures csenv trace ms1 ms2
 
     // Enforce the identities float=float<1>, float32=float32<1> and decimal=decimal<1> 
-    | _, TType_app (tc2, [ms2], nullness2) when tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms2]) ->
+    | _, TType_app (tc2, [ms2], _) when tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms2]) ->
         SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms2 (TType_measure Measure.One) ++ (fun () -> 
-           SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) nullness2
+           SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
         )
 
-    | TType_app (tc1, [ms1], nullness1), _ when tc1.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc1 [ms1]) ->
+    | TType_app (tc1, [ms1], _), _ when tc1.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc1 [ms1]) ->
         SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms1 (TType_measure Measure.One) ++ (fun () -> 
-           SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 nullness1 (nullnessOfTy g sty2)
+           SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
         )
 
     // Special subsumption rule for byref tags
@@ -1452,9 +1452,9 @@ and SolveTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optional
            }
         | _ -> SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2
 
-    | TType_app (tc1, l1, nullness1)  , TType_app (tc2, l2, nullness2) when tyconRefEq g tc1 tc2  -> 
+    | TType_app (tc1, l1, _)  , TType_app (tc2, l2, _) when tyconRefEq g tc1 tc2  -> 
         SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2 ++ (fun () -> 
-           SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 nullness1 nullness2
+           SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
         )
 
     | TType_ucase (uc1, l1), TType_ucase (uc2, l2) when g.unionCaseRefEq uc1 uc2  -> 
@@ -2551,7 +2551,8 @@ and SolveTypeUseNotSupportsNull (csenv: ConstraintSolverEnv) ndeep m2 trace ty =
         // code via Option.ofObj and Option.toObj
         do! WarnD (ConstraintSolverNullnessWarning(FSComp.SR.csTypeHasNullAsTrueValue(NicePrint.minimalStringOfType denv ty), m, m2))
     elif TypeNullIsExtraValueNew g m ty then 
-        if g.checkNullness && not (isObjTy g ty) then 
+        if g.checkNullness && not (isObjTy g ty) then
+            let denv = { denv with showNullnessAnnotations = Some true }
             do! WarnD (ConstraintSolverNullnessWarning(FSComp.SR.csTypeHasNullAsExtraValue(NicePrint.minimalStringOfType denv ty), m, m2))
     else
         match tryDestTyparTy g ty with
@@ -2578,6 +2579,7 @@ and SolveNullnessNotSupportsNull (csenv: ConstraintSolverEnv) ndeep m2 (trace: O
         | NullnessInfo.WithoutNull -> ()
         | NullnessInfo.WithNull -> 
             if g.checkNullness && TypeNullIsExtraValueNew g m ty && not (isObjTy g ty) then
+                let denv = { denv with showNullnessAnnotations = Some true }
                 return! WarnD(ConstraintSolverNullnessWarning(FSComp.SR.csTypeHasNullAsExtraValue(NicePrint.minimalStringOfType denv ty), m, m2))
   }
 
diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs
index 7412023285c..6ff67cf9d63 100644
--- a/src/Compiler/Checking/NicePrint.fs
+++ b/src/Compiler/Checking/NicePrint.fs
@@ -320,6 +320,13 @@ module internal PrintUtilities =
         | Some w -> Display.squashTo w layout
         | None -> layout
         
+    // When showing types in diagnostics, we don't show nullness annotations by default
+    // unless the diagnostic is specifically about nullness.
+    let suppressNullnessAnnotations denv =
+        match denv.showNullnessAnnotations with
+        | None -> { denv with showNullnessAnnotations = Some false }
+        | _ -> denv
+
 module PrintIL = 
 
     let fullySplitILTypeRef (tref: ILTypeRef) = 
@@ -879,7 +886,8 @@ module PrintTypes =
             | args -> bracketIfL (prec <= 1) (bracketL (layoutTypesWithInfoAndPrec denv env 2 (sepL (tagPunctuation ",")) args) --- tcL)
 
     and layoutNullness (denv: DisplayEnv) part2 (nullness: Nullness) =
-        if denv.showNullnessAnnotations then
+        // Show nullness annotations unless explicitly turned off
+        if denv.showNullnessAnnotations <> Some false then
             match nullness.Evaluate() with
             | NullnessInfo.WithNull -> part2 ^^ wordL (tagText "__withnull")
             | NullnessInfo.WithoutNull -> part2
@@ -1227,6 +1235,7 @@ module PrintTastMemberOrVals =
         nameL
 
     let prettyLayoutOfMemberShortOption denv typarInst (v: Val) short =
+        let denv = suppressNullnessAnnotations denv
         let vref = mkLocalValRef v
         let membInfo = Option.get vref.MemberInfo
         let stat = layoutMemberFlags membInfo.MemberFlags
@@ -2658,9 +2667,11 @@ let prettyLayoutOfInstAndSig denv x = PrintTypes.prettyLayoutOfInstAndSig denv x
 let minimalStringsOfTwoTypes denv ty1 ty2 =
     let (ty1, ty2), tpcs = PrettyTypes.PrettifyTypePair denv.g (ty1, ty2)
 
+    let denv = suppressNullnessAnnotations denv
+
     // try denv + no type annotations 
     let attempt1 = 
-        let denv = { denv with showInferenceTyparAnnotations=false; showStaticallyResolvedTyparAnnotations=false; showNullnessAnnotations=false }
+        let denv = { denv with showInferenceTyparAnnotations=false; showStaticallyResolvedTyparAnnotations=false }
         let min1 = stringOfTy denv ty1
         let min2 = stringOfTy denv ty2
         if min1 <> min2 then Some (min1, min2, "") else None
@@ -2671,7 +2682,7 @@ let minimalStringsOfTwoTypes denv ty1 ty2 =
 
     // try denv + no type annotations + show full paths
     let attempt2 = 
-        let denv = { denv with showInferenceTyparAnnotations=false; showStaticallyResolvedTyparAnnotations=false; showNullnessAnnotations=false }.SetOpenPaths []
+        let denv = { denv with showInferenceTyparAnnotations=false; showStaticallyResolvedTyparAnnotations=false }.SetOpenPaths []
         let min1 = stringOfTy denv ty1
         let min2 = stringOfTy denv ty2
         if min1 <> min2 then Some (min1, min2, "") else None
@@ -2713,18 +2724,20 @@ let minimalStringsOfTwoTypes denv ty1 ty2 =
     
 // Note: Always show imperative annotations when comparing value signatures 
 let minimalStringsOfTwoValues denv infoReader vref1 vref2 = 
-    let denvMin = { denv with showInferenceTyparAnnotations=true; showStaticallyResolvedTyparAnnotations=false; showNullnessAnnotations=false }
+    let denv = suppressNullnessAnnotations denv
+    let denvMin = { denv with showInferenceTyparAnnotations=true; showStaticallyResolvedTyparAnnotations=false }
     let min1 = buildString (fun buf -> outputQualifiedValOrMember denvMin infoReader buf vref1)
     let min2 = buildString (fun buf -> outputQualifiedValOrMember denvMin infoReader buf vref2) 
     if min1 <> min2 then 
         (min1, min2) 
     else
-        let denvMax = { denv with showInferenceTyparAnnotations=true; showStaticallyResolvedTyparAnnotations=true; showNullnessAnnotations=false }
+        let denvMax = { denv with showInferenceTyparAnnotations=true; showStaticallyResolvedTyparAnnotations=true }
         let max1 = buildString (fun buf -> outputQualifiedValOrMember denvMax infoReader buf vref1)
         let max2 = buildString (fun buf -> outputQualifiedValOrMember denvMax infoReader buf vref2) 
         max1, max2
     
 let minimalStringOfType denv ty = 
     let ty, _cxs = PrettyTypes.PrettifyType denv.g ty
+    let denv = suppressNullnessAnnotations denv
     let denvMin = { denv with showInferenceTyparAnnotations=false; showStaticallyResolvedTyparAnnotations=false }
     showL (PrintTypes.layoutTypeWithInfoAndPrec denvMin SimplifyTypes.typeSimplificationInfo0 2 ty)
diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs
index 6c6c64d4a20..ca8ff57c0f8 100644
--- a/src/Compiler/Driver/CompilerDiagnostics.fs
+++ b/src/Compiler/Driver/CompilerDiagnostics.fs
@@ -678,6 +678,9 @@ type Exception with
 
         | ConstraintSolverNullnessWarningEquivWithTypes (denv, ty1, ty2, _nullness1, _nullness2, m, m2) ->
 
+            // Turn on nullness annotations for messages about nullness
+            let denv = { denv with showNullnessAnnotations = Some true }
+
             let t1, t2, _cxs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2
 
             os.Append(ConstraintSolverNullnessWarningEquivWithTypesE().Format t1 t2)
@@ -688,6 +691,9 @@ type Exception with
 
         | ConstraintSolverNullnessWarningWithTypes (denv, ty1, ty2, _nullness1, _nullness2, m, m2) ->
 
+            // Turn on nullness annotations for messages about nullness
+            let denv = { denv with showNullnessAnnotations = Some true }
+
             let t1, t2, _cxs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2
 
             os.Append(ConstraintSolverNullnessWarningWithTypesE().Format t1 t2) |> ignore
@@ -697,6 +703,9 @@ type Exception with
 
         | ConstraintSolverNullnessWarningWithType (denv, ty, _, m, m2) ->
 
+            // Turn on nullness annotations for messages about nullness
+            let denv = { denv with showNullnessAnnotations = Some true }
+
             let t = NicePrint.minimalStringOfType denv ty
             os.Append(ConstraintSolverNullnessWarningWithTypeE().Format(t)) |> ignore
 
diff --git a/src/Compiler/Interactive/fsi.fs b/src/Compiler/Interactive/fsi.fs
index 97c3cc08d84..605981c6361 100644
--- a/src/Compiler/Interactive/fsi.fs
+++ b/src/Compiler/Interactive/fsi.fs
@@ -3439,7 +3439,7 @@ type internal MagicAssemblyResolution() =
             fsiDynamicCompiler: FsiDynamicCompiler,
             fsiConsoleOutput: FsiConsoleOutput,
             fullAssemName: string
-        ) =
+        ) : Assembly MaybeNull =
 
         //Eliminate recursive calls to Resolve which can happen via our callout to msbuild resolution
         if MagicAssemblyResolution.resolving then
@@ -3527,14 +3527,14 @@ type FsiStdinLexerProvider
                     | NonNull t -> fsiStdinSyphon.Add(t + "\n"))
 
                 match inputOption with
-                | Some null
+                | Some Null
                 | None ->
                     if progress then
                         fprintfn fsiConsoleOutput.Out "End of file from TextReader.ReadLine"
 
                     0
-                | Some (input: string) ->
-                    let input = input + "\n"
+                | Some (NonNull input) ->
+                    let input = nonNull input + "\n"
 
                     if input.Length > len then
                         fprintf fsiConsoleOutput.Error "%s" (FSIstrings.SR.fsiLineTooLong ())
diff --git a/src/Compiler/Symbols/SymbolHelpers.fs b/src/Compiler/Symbols/SymbolHelpers.fs
index 11a9623bff1..9ac979fa9da 100644
--- a/src/Compiler/Symbols/SymbolHelpers.fs
+++ b/src/Compiler/Symbols/SymbolHelpers.fs
@@ -543,7 +543,7 @@ module internal SymbolHelpers =
     let SimplerDisplayEnv denv = 
         { denv with shortConstraints=true
                     showStaticallyResolvedTyparAnnotations=false
-                    showNullnessAnnotations=false
+                    showNullnessAnnotations = Some false
                     abbreviateAdditionalConstraints=false
                     suppressNestedTypes=true
                     maxMembers=Some EnvMisc2.maxMembers }
diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs
index 3f92f88a3e6..4820483d675 100755
--- a/src/Compiler/TypedTree/TcGlobals.fs
+++ b/src/Compiler/TypedTree/TcGlobals.fs
@@ -196,6 +196,9 @@ type TcGlobals(
 
   let v_langFeatureNullness = langVersion.SupportsFeature LanguageFeature.NullnessChecking
 
+  let v_knownWithNull =
+      if v_langFeatureNullness then KnownWithNull else KnownAmbivalentToNull
+
   let v_knownWithoutNull =
       if v_langFeatureNullness then KnownWithoutNull else KnownAmbivalentToNull
 
@@ -1091,6 +1094,8 @@ type TcGlobals(
 
   member _.langFeatureNullness = v_langFeatureNullness
 
+  member _.knownWithNull = v_knownWithNull
+
   member _.knownWithoutNull = v_knownWithoutNull
 
   // A table of known modules in FSharp.Core. Not all modules are necessarily listed, but the more we list the
diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs
index d884826c2e2..b2d86d3285c 100644
--- a/src/Compiler/TypedTree/TypedTreeOps.fs
+++ b/src/Compiler/TypedTree/TypedTreeOps.fs
@@ -863,8 +863,6 @@ let destAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, tinst, _)
 
 let tcrefOfAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> tcref | _ -> failwith "tcrefOfAppTy") 
 
-let nullnessOfTy g ty = ty |> stripTyEqns g |> (function TType_app(_, _, nullness) | TType_fun (_, _, nullness) | TType_var (_, nullness) -> nullness | _ -> g.knownWithoutNull) 
-
 let argsOfAppTy g ty = ty |> stripTyEqns g |> (function TType_app(_, tinst, _) -> tinst | _ -> [])
 
 let tryDestTyparTy g ty = ty |> stripTyEqns g |> (function TType_var (v, _) -> ValueSome v | _ -> ValueNone)
@@ -3078,7 +3076,7 @@ type DisplayEnv =
       showAttributes: bool
       showOverrides: bool
       showStaticallyResolvedTyparAnnotations: bool
-      showNullnessAnnotations: bool
+      showNullnessAnnotations: bool option
       abbreviateAdditionalConstraints: bool
       showTyparDefaultConstraints: bool
       showDocumentation: bool
@@ -3113,7 +3111,7 @@ type DisplayEnv =
         showAttributes = false
         showOverrides = true
         showStaticallyResolvedTyparAnnotations = true
-        showNullnessAnnotations = true
+        showNullnessAnnotations = None
         showDocumentation = false
         abbreviateAdditionalConstraints = false
         showTyparDefaultConstraints = false
@@ -8906,16 +8904,16 @@ let TypeNullNever g ty =
     isByrefTy g underlyingTy ||
     isNonNullableStructTyparTy g ty
 
-/// The F# 4.5 logic about whether a type admits the use of 'null' as a value.
+/// The pre-nullness logic about whether a type admits the use of 'null' as a value.
 let TypeNullIsExtraValue g m ty = 
     if isILReferenceTy g ty || isDelegateTy g ty then
         match tryTcrefOfAppTy g ty with 
         | ValueSome tcref -> 
-            // In F# 4.x, putting AllowNullLiteralAttribute(false) on an IL or provided 
+            // Putting AllowNullLiteralAttribute(false) on an IL or provided 
             // type means 'null' can't be used with that type, otherwise it can
             TryFindTyconRefBoolAttribute g m g.attrib_AllowNullLiteralAttribute tcref <> Some false 
         | _ -> 
-            // In F# 4.5, other IL reference types (e.g. arrays) always support null
+            // In pre-nullness, other IL reference types (e.g. arrays) always support null
             true
     elif TypeNullNever g ty then 
         false
@@ -8928,6 +8926,23 @@ let TypeNullIsExtraValue g m ty =
         // Consider type parameters
         isSupportsNullTyparTy g ty
 
+// Any mention of a type with AllowNullLiteral(true) is considered to be with-null
+let intrinsicNullnessOfTyconRef g (tcref: TyconRef) =
+    match TryFindTyconRefBoolAttribute g tcref.Range g.attrib_AllowNullLiteralAttribute tcref with
+    | Some true -> g.knownWithNull
+    | _ -> g.knownWithoutNull
+
+let nullnessOfTy g ty =
+    ty
+    |> stripTyEqns g
+    |> function
+        | TType_app(tcref, _, nullness) ->
+            let nullness2 = intrinsicNullnessOfTyconRef g tcref
+            combineNullness nullness nullness2
+        | TType_fun (_, _, nullness) | TType_var (_, nullness) ->
+            nullness
+        | _ -> g.knownWithoutNull
+
 /// The new logic about whether a type admits the use of 'null' as a value.
 let TypeNullIsExtraValueNew g m ty = 
     let sty = stripTyparEqns ty
@@ -8952,7 +8967,7 @@ let TypeNullIsExtraValueNew g m ty =
     // Check if the type has a ': null' constraint
     isSupportsNullTyparTy g ty
 
-/// The F# 4.5 and 5.0 logic about whether a type uses 'null' as a true representation value
+/// The pre-nullness logic about whether a type uses 'null' as a true representation value
 let TypeNullIsTrueValue g ty =
     (match tryTcrefOfAppTy g ty with
      | ValueSome tcref -> IsUnionTypeWithNullAsTrueValue g tcref.Deref
diff --git a/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi
index db8d887358a..a7ae81fb761 100755
--- a/src/Compiler/TypedTree/TypedTreeOps.fsi
+++ b/src/Compiler/TypedTree/TypedTreeOps.fsi
@@ -1061,7 +1061,7 @@ type DisplayEnv =
         showAttributes: bool
         showOverrides: bool
         showStaticallyResolvedTyparAnnotations: bool
-        showNullnessAnnotations: bool
+        showNullnessAnnotations: bool option
         abbreviateAdditionalConstraints: bool
         showTyparDefaultConstraints: bool
         /// If set, signatures will be rendered with XML documentation comments for members if they exist
diff --git a/src/Compiler/Utilities/illib.fs b/src/Compiler/Utilities/illib.fs
index 7942b78593e..699c9a2908b 100644
--- a/src/Compiler/Utilities/illib.fs
+++ b/src/Compiler/Utilities/illib.fs
@@ -90,17 +90,15 @@ module internal PervasiveAutoOpens =
         | Some x -> x
 
     let reportTime =
-        let mutable tPrev: IDisposable = null
+        let mutable tPrev: IDisposable MaybeNull = null
 
         fun descr ->
             if isNotNull tPrev then
                 tPrev.Dispose()
+                tPrev <- null
 
-            tPrev <-
-                if descr <> "Finish" then
-                    FSharp.Compiler.Diagnostics.Activity.Profiling.startAndMeasureEnvironmentStats descr
-                else
-                    null
+            if descr <> "Finish" then
+                tPrev <- FSharp.Compiler.Diagnostics.Activity.Profiling.startAndMeasureEnvironmentStats descr
 
     let foldOn p f z x = f z (p x)
 

From 7b1afe0e602943500279860d8381b27e971ae35c Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Fri, 26 May 2023 14:18:52 +0100
Subject: [PATCH 19/59] fantomas and validation update

---
 src/Compiler/Driver/CompilerDiagnostics.fs    | 15 ++++--
 .../positive.next.enabled.checknulls.bsl      | 52 +++++++++----------
 .../negative.next.enabled.checknulls.bsl      |  6 +--
 .../positive.next.enabled.checknulls.bsl      |  8 +--
 4 files changed, 45 insertions(+), 36 deletions(-)

diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs
index ca8ff57c0f8..e938263699b 100644
--- a/src/Compiler/Driver/CompilerDiagnostics.fs
+++ b/src/Compiler/Driver/CompilerDiagnostics.fs
@@ -679,7 +679,10 @@ type Exception with
         | ConstraintSolverNullnessWarningEquivWithTypes (denv, ty1, ty2, _nullness1, _nullness2, m, m2) ->
 
             // Turn on nullness annotations for messages about nullness
-            let denv = { denv with showNullnessAnnotations = Some true }
+            let denv =
+                { denv with
+                    showNullnessAnnotations = Some true
+                }
 
             let t1, t2, _cxs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2
 
@@ -692,7 +695,10 @@ type Exception with
         | ConstraintSolverNullnessWarningWithTypes (denv, ty1, ty2, _nullness1, _nullness2, m, m2) ->
 
             // Turn on nullness annotations for messages about nullness
-            let denv = { denv with showNullnessAnnotations = Some true }
+            let denv =
+                { denv with
+                    showNullnessAnnotations = Some true
+                }
 
             let t1, t2, _cxs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2
 
@@ -704,7 +710,10 @@ type Exception with
         | ConstraintSolverNullnessWarningWithType (denv, ty, _, m, m2) ->
 
             // Turn on nullness annotations for messages about nullness
-            let denv = { denv with showNullnessAnnotations = Some true }
+            let denv =
+                { denv with
+                    showNullnessAnnotations = Some true
+                }
 
             let t = NicePrint.minimalStringOfType denv ty
             os.Append(ConstraintSolverNullnessWarningWithTypeE().Format(t)) |> ignore
diff --git a/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl b/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl
index f5ea0050726..e4f2b0456f8 100644
--- a/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl
+++ b/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl
@@ -7,54 +7,54 @@ tests\adhoc\nullness\enabled\positive.fs(18,43): warning FS3261: Nullness warnin
 
 tests\adhoc\nullness\enabled\positive.fs(19,26): warning FS3261: Nullness warning: The type 'int option' uses 'null' as a representation value but a non-null type is expected.
 
-tests\adhoc\nullness\enabled\positive.fs(27,14): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(27,14): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(27,14): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(27,14): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(28,14): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(28,14): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(28,14): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(28,14): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(29,14): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(29,14): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(29,14): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(29,14): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(43,26): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\enabled\positive.fs(43,26): warning FS3261: Nullness warning: The type 'String' does not support 'null'.
 
-tests\adhoc\nullness\enabled\positive.fs(85,67): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(85,67): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(85,67): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(85,67): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(86,89): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(86,89): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(86,89): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(86,89): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(86,100): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(86,100): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(86,100): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(86,100): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(91,57): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(91,57): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(91,57): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(91,57): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(92,80): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(92,80): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(92,80): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(92,80): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(92,91): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(92,91): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(92,91): warning FS3261: Nullness warning: A non-null type is expected. The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(92,91): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(120,32): warning FS3261: Nullness warning: The type 'obj array' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\enabled\positive.fs(120,32): warning FS3261: Nullness warning: The type 'obj array' does not support 'null'.
 
-tests\adhoc\nullness\enabled\positive.fs(129,4): warning FS3261: Nullness warning: A non-null type is expected. The types 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' and 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(129,4): warning FS3261: Nullness warning: The types 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' and 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(134,5): warning FS3261: Nullness warning: A non-null type is expected. The types 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' and 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(134,5): warning FS3261: Nullness warning: The types 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' and 'System.String (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(159,36): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\enabled\positive.fs(159,36): warning FS3261: Nullness warning: The type 'String' does not support 'null'.
 
-tests\adhoc\nullness\enabled\positive.fs(162,41): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\enabled\positive.fs(162,41): warning FS3261: Nullness warning: The type 'String' does not support 'null'.
 
-tests\adhoc\nullness\enabled\positive.fs(164,37): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\enabled\positive.fs(164,37): warning FS3261: Nullness warning: The type 'String' does not support 'null'.
 
-tests\adhoc\nullness\enabled\positive.fs(189,17): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\enabled\positive.fs(189,17): warning FS3261: Nullness warning: The type 'String' does not support 'null'.
diff --git a/tests/adhoc/nullness/existing/negative.next.enabled.checknulls.bsl b/tests/adhoc/nullness/existing/negative.next.enabled.checknulls.bsl
index ca1be2e32fc..5244ca862a8 100644
--- a/tests/adhoc/nullness/existing/negative.next.enabled.checknulls.bsl
+++ b/tests/adhoc/nullness/existing/negative.next.enabled.checknulls.bsl
@@ -1,9 +1,9 @@
 
-tests\adhoc\nullness\existing\negative.fs(8,17): warning FS3261: Nullness warning: The type '(int * int)' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\existing\negative.fs(8,17): warning FS3261: Nullness warning: The type '(int * int)' does not support 'null'.
 
-tests\adhoc\nullness\existing\negative.fs(12,17): warning FS3261: Nullness warning: The type '(int -> int)' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\existing\negative.fs(12,17): warning FS3261: Nullness warning: The type '(int -> int)' does not support 'null'.
 
-tests\adhoc\nullness\existing\negative.fs(20,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
+tests\adhoc\nullness\existing\negative.fs(20,25): warning FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
 
 tests\adhoc\nullness\existing\negative.fs(25,25): error FS0444: The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check
 
diff --git a/tests/adhoc/nullness/existing/positive.next.enabled.checknulls.bsl b/tests/adhoc/nullness/existing/positive.next.enabled.checknulls.bsl
index c83ee6b5bc2..2788d57d704 100644
--- a/tests/adhoc/nullness/existing/positive.next.enabled.checknulls.bsl
+++ b/tests/adhoc/nullness/existing/positive.next.enabled.checknulls.bsl
@@ -1,8 +1,8 @@
 
-tests\adhoc\nullness\existing\positive.fs(24,23): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\existing\positive.fs(24,23): warning FS3261: Nullness warning: The type 'String' does not support 'null'.
 
-tests\adhoc\nullness\existing\positive.fs(29,26): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\existing\positive.fs(29,26): warning FS3261: Nullness warning: The type 'String' does not support 'null'.
 
-tests\adhoc\nullness\existing\positive.fs(44,32): warning FS3261: Nullness warning: The type 'obj array' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\existing\positive.fs(44,32): warning FS3261: Nullness warning: The type 'obj array' does not support 'null'.
 
-tests\adhoc\nullness\existing\positive.fs(55,17): warning FS3261: Nullness warning: The type 'String' is non-null, but a type supporting 'null' is expected.
+tests\adhoc\nullness\existing\positive.fs(55,17): warning FS3261: Nullness warning: The type 'String' does not support 'null'.

From ffbbfd28d0ddc20018b98b40e507cc3af499fd57 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Fri, 26 May 2023 15:09:10 +0100
Subject: [PATCH 20/59] corrections to self-use

---
 FSharp.Profiles.props                       | 5 +++--
 src/Compiler/FSharp.Compiler.Service.fsproj | 1 -
 src/Compiler/TypedTree/TypeProviders.fs     | 6 +++---
 src/FSharp.Build/FSharp.Build.fsproj        | 1 -
 4 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/FSharp.Profiles.props b/FSharp.Profiles.props
index 27aaa965d68..dbbe1903539 100644
--- a/FSharp.Profiles.props
+++ b/FSharp.Profiles.props
@@ -2,8 +2,9 @@
 
 
   
-    
-    false
+    
+    
+    false
   
 
   
diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj
index af5e504d33c..a5648ed457f 100644
--- a/src/Compiler/FSharp.Compiler.Service.fsproj
+++ b/src/Compiler/FSharp.Compiler.Service.fsproj
@@ -13,7 +13,6 @@
     FSharp.Compiler.Service
     true
     $(DefineConstants);COMPILER
-    true
     $(DefineConstants);FSHARPCORE_USE_PACKAGE
     $(OtherFlags) --extraoptimizationloops:1
     
diff --git a/src/Compiler/TypedTree/TypeProviders.fs b/src/Compiler/TypedTree/TypeProviders.fs
index fbb1899bcd1..34eefe3d3e4 100644
--- a/src/Compiler/TypedTree/TypeProviders.fs
+++ b/src/Compiler/TypedTree/TypeProviders.fs
@@ -1122,7 +1122,7 @@ let ValidateExpectedName m expectedPath expectedName (st: Tainted)
 #if NO_CHECKNULLS
     let namespaceName = TryTypeMember(st, name, "Namespace", m, "", fun st -> st.Namespace) |> unmarshal
 #else
-    let namespaceName = TryTypeMember<_, string?>(st, name, "Namespace", m, "", fun st -> st.Namespace) |> unmarshal // TODO NULLNESS: why is this explicit instantiation needed?
+    let namespaceName = TryTypeMember<_, string __withnull>(st, name, "Namespace", m, "", fun st -> st.Namespace) |> unmarshal // TODO NULLNESS: why is this explicit instantiation needed?
 #endif
 
     let rec declaringTypes (st: Tainted) accu =
@@ -1149,7 +1149,7 @@ let ValidateProvidedTypeAfterStaticInstantiation(m, st: Tainted, e
 #if NO_CHECKNULLS
         let namespaceName = TryTypeMember(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal
 #else
-        let namespaceName = TryTypeMember<_, string?>(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal
+        let namespaceName = TryTypeMember<_, string __withnull>(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal
 #endif
         let fullName = TryTypeMemberNonNull(st, name, "FullName", m, FSComp.SR.invalidFullNameForProvidedType(), fun st -> st.FullName) |> unmarshal
         ValidateExpectedName m expectedPath expectedName st
@@ -1258,7 +1258,7 @@ let ValidateProvidedTypeDefinition(m, st: Tainted, expectedPath: s
 #if NO_CHECKNULLS
     let _namespaceName = TryTypeMember(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal
 #else
-    let _namespaceName = TryTypeMember<_, (string?)>(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal
+    let _namespaceName = TryTypeMember<_, string __withnull>(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal
 #endif
     let _fullname = TryTypeMemberNonNull(st, name, "FullName", m, FSComp.SR.invalidFullNameForProvidedType(), fun st -> st.FullName)  |> unmarshal
     ValidateExpectedName m expectedPath expectedName st
diff --git a/src/FSharp.Build/FSharp.Build.fsproj b/src/FSharp.Build/FSharp.Build.fsproj
index a159fb8d43b..f8fbc7138ef 100644
--- a/src/FSharp.Build/FSharp.Build.fsproj
+++ b/src/FSharp.Build/FSharp.Build.fsproj
@@ -9,7 +9,6 @@
     FSharp.Build
     $(NoWarn);75 
     true
-    true
     $(DefineConstants);LOCALIZATION_FSBUILD
     $(NoWarn);NU1701;FS0075
     true

From 559c058144129e0a42de3f66f9844c60e9c620f9 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Fri, 2 Jun 2023 17:44:20 +0100
Subject: [PATCH 21/59] [WIP] [RFC FS-1060] Nullness checking (applied to
 codebase) (#15265)

* enablement

* enablement

* fix build

* fix build

* fantomas

* selective adoption
---
 src/Compiler/FSharp.Compiler.Service.fsproj | 1 +
 src/FSharp.Build/FSharp.Build.fsproj        | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj
index a5648ed457f..af5e504d33c 100644
--- a/src/Compiler/FSharp.Compiler.Service.fsproj
+++ b/src/Compiler/FSharp.Compiler.Service.fsproj
@@ -13,6 +13,7 @@
     FSharp.Compiler.Service
     true
     $(DefineConstants);COMPILER
+    true
     $(DefineConstants);FSHARPCORE_USE_PACKAGE
     $(OtherFlags) --extraoptimizationloops:1
     
diff --git a/src/FSharp.Build/FSharp.Build.fsproj b/src/FSharp.Build/FSharp.Build.fsproj
index f8fbc7138ef..a159fb8d43b 100644
--- a/src/FSharp.Build/FSharp.Build.fsproj
+++ b/src/FSharp.Build/FSharp.Build.fsproj
@@ -9,6 +9,7 @@
     FSharp.Build
     $(NoWarn);75 
     true
+    true
     $(DefineConstants);LOCALIZATION_FSBUILD
     $(NoWarn);NU1701;FS0075
     true

From a2edfd270c35301ed427f0e965805c7f9d626c60 Mon Sep 17 00:00:00 2001
From: Don Syme 
Date: Mon, 5 Jun 2023 12:47:27 +0100
Subject: [PATCH 22/59] Revert "[WIP] [RFC FS-1060] Nullness checking (applied
 to codebase) (#15265)" (#15309)

This reverts commit 559c058144129e0a42de3f66f9844c60e9c620f9.
---
 src/Compiler/FSharp.Compiler.Service.fsproj | 1 -
 src/FSharp.Build/FSharp.Build.fsproj        | 1 -
 2 files changed, 2 deletions(-)

diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj
index af5e504d33c..a5648ed457f 100644
--- a/src/Compiler/FSharp.Compiler.Service.fsproj
+++ b/src/Compiler/FSharp.Compiler.Service.fsproj
@@ -13,7 +13,6 @@
     FSharp.Compiler.Service
     true
     $(DefineConstants);COMPILER
-    true
     $(DefineConstants);FSHARPCORE_USE_PACKAGE
     $(OtherFlags) --extraoptimizationloops:1
     
diff --git a/src/FSharp.Build/FSharp.Build.fsproj b/src/FSharp.Build/FSharp.Build.fsproj
index a159fb8d43b..f8fbc7138ef 100644
--- a/src/FSharp.Build/FSharp.Build.fsproj
+++ b/src/FSharp.Build/FSharp.Build.fsproj
@@ -9,7 +9,6 @@
     FSharp.Build
     $(NoWarn);75 
     true
-    true
     $(DefineConstants);LOCALIZATION_FSBUILD
     $(NoWarn);NU1701;FS0075
     true

From 9a58eb4e8c10f8a64fb8f51abb598c85f3789b62 Mon Sep 17 00:00:00 2001
From: Vlad Zarytovskii 
Date: Thu, 7 Sep 2023 15:28:40 +0200
Subject: [PATCH 23/59] Fixes

---
 src/Compiler/xlf/FSComp.txt.cs.xlf      | 40 +++++++++++++++++++++++++
 src/Compiler/xlf/FSComp.txt.de.xlf      | 40 +++++++++++++++++++++++++
 src/Compiler/xlf/FSComp.txt.es.xlf      | 40 +++++++++++++++++++++++++
 src/Compiler/xlf/FSComp.txt.fr.xlf      | 40 +++++++++++++++++++++++++
 src/Compiler/xlf/FSComp.txt.it.xlf      | 40 +++++++++++++++++++++++++
 src/Compiler/xlf/FSComp.txt.ja.xlf      | 40 +++++++++++++++++++++++++
 src/Compiler/xlf/FSComp.txt.ko.xlf      | 40 +++++++++++++++++++++++++
 src/Compiler/xlf/FSComp.txt.pl.xlf      | 40 +++++++++++++++++++++++++
 src/Compiler/xlf/FSComp.txt.pt-BR.xlf   | 40 +++++++++++++++++++++++++
 src/Compiler/xlf/FSComp.txt.ru.xlf      | 40 +++++++++++++++++++++++++
 src/Compiler/xlf/FSComp.txt.tr.xlf      | 40 +++++++++++++++++++++++++
 src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 40 +++++++++++++++++++++++++
 src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 40 +++++++++++++++++++++++++
 src/Compiler/xlf/FSStrings.cs.xlf       | 30 +++++++++++++++++++
 src/Compiler/xlf/FSStrings.de.xlf       | 30 +++++++++++++++++++
 src/Compiler/xlf/FSStrings.es.xlf       | 30 +++++++++++++++++++
 src/Compiler/xlf/FSStrings.fr.xlf       | 30 +++++++++++++++++++
 src/Compiler/xlf/FSStrings.it.xlf       | 30 +++++++++++++++++++
 src/Compiler/xlf/FSStrings.ja.xlf       | 30 +++++++++++++++++++
 src/Compiler/xlf/FSStrings.ko.xlf       | 30 +++++++++++++++++++
 src/Compiler/xlf/FSStrings.pl.xlf       | 30 +++++++++++++++++++
 src/Compiler/xlf/FSStrings.pt-BR.xlf    | 30 +++++++++++++++++++
 src/Compiler/xlf/FSStrings.ru.xlf       | 30 +++++++++++++++++++
 src/Compiler/xlf/FSStrings.tr.xlf       | 30 +++++++++++++++++++
 src/Compiler/xlf/FSStrings.zh-Hans.xlf  | 30 +++++++++++++++++++
 src/Compiler/xlf/FSStrings.zh-Hant.xlf  | 30 +++++++++++++++++++
 src/FSharp.Core/option.fs               |  4 +--
 27 files changed, 912 insertions(+), 2 deletions(-)

diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf
index df678fb3840..39c15c88278 100644
--- a/src/Compiler/xlf/FSComp.txt.cs.xlf
+++ b/src/Compiler/xlf/FSComp.txt.cs.xlf
@@ -162,6 +162,11 @@
         Známý typ parametru: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         Argument na indexu {0} neodpovídá
@@ -172,6 +177,16 @@
         Argument {0} neodpovídá
         
       
+      
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
+        
+      
+      
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        
+      
       
         The constraints 'unmanaged' and 'not struct' are inconsistent
         The constraints 'unmanaged' and 'not struct' are inconsistent
@@ -197,6 +212,11 @@
         Atribut sestavení {0} odkazuje na navržené sestavení {1}, které se nedá načíst nebo neexistuje. Ohlášená výjimka: {2} – {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         underscore dot shorthand for accessor only function
         underscore dot shorthand for accessor only function
@@ -382,6 +402,11 @@
         nepovinný zprostředkovatel komunikace s možnou hodnotou null
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         Otevřít deklaraci typu
@@ -732,6 +757,11 @@
         Vytiskněte odvozená rozhraní všech kompilovaných souborů do přidružených souborů podpisu.
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Vymazat mezipaměť výsledků správce balíčků
@@ -1262,6 +1292,11 @@
         Hodnota {0} není funkce a nepodporuje zápis indexu.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         Syntaxe expr1[expr2] je při použití jako argument nejednoznačná. Více informací: https://aka.ms/fsharp-index-notation. Pokud plánujete indexování nebo vytváření řezů, musíte použít expr1.[expr2] na pozici argumentu. Pokud voláte funkci s vícenásobnými curryfikovanými argumenty, přidejte mezi ně mezeru, třeba someFunction expr1 [expr2].
@@ -1367,6 +1402,11 @@
         Vlastnost nesmí určovat volitelné argumenty, in, out, ParamArray, CallerInfo nebo Quote.
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         Invalid interpolated string. {0}
         Neplatný interpolovaný řetězec. {0}
diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf
index ae083bc3434..e2fe7ea06ba 100644
--- a/src/Compiler/xlf/FSComp.txt.de.xlf
+++ b/src/Compiler/xlf/FSComp.txt.de.xlf
@@ -162,6 +162,11 @@
         Bekannter Typparameter: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         Das Argument bei Index {0} stimmt nicht überein.
@@ -172,6 +177,16 @@
         Das Argument "{0}" stimmt nicht überein.
         
       
+      
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
+        
+      
+      
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        
+      
       
         The constraints 'unmanaged' and 'not struct' are inconsistent
         The constraints 'unmanaged' and 'not struct' are inconsistent
@@ -197,6 +212,11 @@
         Das Assemblyattribut "{0}" verweist auf eine Designerassembly "{1}", die entweder nicht geladen werden kann oder nicht vorhanden ist. Gemeldete Ausnahme: {2} – {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         underscore dot shorthand for accessor only function
         underscore dot shorthand for accessor only function
@@ -382,6 +402,11 @@
         Interop, NULL-Werte zulassend, optional
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         Deklaration für offene Typen
@@ -732,6 +757,11 @@
         Drucken der abgeleiteten Schnittstellen aller Dateien an zugehörige Signaturdateien
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Löschen Sie den Ergebniscache des Paketmanagers
@@ -1262,6 +1292,11 @@
         Der Wert "{0}" ist keine Funktion und unterstützt keine Indexnotation.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         Die Syntax "expr1[expr2]" ist mehrdeutig, wenn sie als Argument verwendet wird. Siehe https://aka.ms/fsharp-index-notation. Wenn Sie indizieren oder aufteilen möchten, müssen Sie "expr1.[expr2]' in Argumentposition verwenden. Wenn Sie eine Funktion mit mehreren geschweiften Argumenten aufrufen, fügen Sie ein Leerzeichen dazwischen hinzu, z. B. "someFunction expr1 [expr2]".
@@ -1367,6 +1402,11 @@
         Ein Merkmal darf keine Argumente für „optional“, „in“, „out“, „ParamArray“", „CallerInfo“ oder „Quote“ angeben.
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         Invalid interpolated string. {0}
         Ungültige interpolierte Zeichenfolge. {0}
diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf
index 43932120280..2fb53260cf5 100644
--- a/src/Compiler/xlf/FSComp.txt.es.xlf
+++ b/src/Compiler/xlf/FSComp.txt.es.xlf
@@ -162,6 +162,11 @@
         Parámetro de tipo conocido: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         El argumento del índice {0} no coincide.
@@ -172,6 +177,16 @@
         El argumento "{0}" no coincide.
         
       
+      
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
+        
+      
+      
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        
+      
       
         The constraints 'unmanaged' and 'not struct' are inconsistent
         The constraints 'unmanaged' and 'not struct' are inconsistent
@@ -197,6 +212,11 @@
         El atributo de ensamblado "{0}" hace referencia a un ensamblado de diseñador "{1}" que no se puede cargar o no existe. Se notificó la excepción: {2} - {3}.
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         underscore dot shorthand for accessor only function
         underscore dot shorthand for accessor only function
@@ -382,6 +402,11 @@
         interoperabilidad opcional que admite valores NULL
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         declaración de tipo abierto
@@ -732,6 +757,11 @@
         Imprimir las interfaces deducidas de todos los archivos de compilación en los archivos de signatura asociados
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Borrar la caché de resultados del administrador de paquetes
@@ -1262,6 +1292,11 @@
         El valor "{0}" no es una función y no admite la notación de índices.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         La sintaxis "expr1[expr2]" es ambigua cuando se usa como argumento. Vea https://aka.ms/fsharp-index-notation. Si piensa indexar o segmentar, debe usar "expr1.[expr2]" en la posición del argumento. Si se llama a una función con varios argumentos currificados, se agregará un espacio entre ellos, por ejemplo, "unaFunción expr1 [expr2]".
@@ -1367,6 +1402,11 @@
         Un rasgo no puede especificar argumentos opcionales, in, out, ParamArray, CallerInfo o Quote
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         Invalid interpolated string. {0}
         Cadena interpolada no válida. {0}
diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf
index f556dc0e60c..33607d5c1c8 100644
--- a/src/Compiler/xlf/FSComp.txt.fr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.fr.xlf
@@ -162,6 +162,11 @@
         Paramètre de type connu : {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         L'argument à l'index {0} ne correspond pas
@@ -172,6 +177,16 @@
         L'argument '{0}' ne correspond pas
         
       
+      
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
+        
+      
+      
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        
+      
       
         The constraints 'unmanaged' and 'not struct' are inconsistent
         The constraints 'unmanaged' and 'not struct' are inconsistent
@@ -197,6 +212,11 @@
         L'attribut d'assembly '{0}' fait référence à un assembly de concepteur '{1}' qui ne peut pas être chargé ou qui n'existe pas. Exception signalée : {2} - {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         underscore dot shorthand for accessor only function
         underscore dot shorthand for accessor only function
@@ -382,6 +402,11 @@
         interopérabilité facultative pouvant accepter une valeur null
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         déclaration de type ouverte
@@ -732,6 +757,11 @@
         Imprimer les interfaces inférées de tous les fichiers de compilation sur les fichiers de signature associés
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Effacer le cache des résultats du Gestionnaire de package
@@ -1262,6 +1292,11 @@
         La valeur « {0} » n’est pas une fonction et ne prend pas en charge la notation d’index.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         La syntaxe « expr1[expr2] » est ambiguë lorsqu’elle est utilisée comme argument. Voir https://aka.ms/fsharp-index-notation. Si vous avez l’intention d’indexer ou de découper, vous devez utiliser « expr1.[expr2] » en position d’argument. Si vous appelez une fonction avec plusieurs arguments codés, ajoutez un espace entre eux, par exemple « someFunction expr1 [expr2] ».
@@ -1367,6 +1402,11 @@
         Une caractéristique ne peut pas spécifier d’arguments facultatifs, in, out, ParamArray, CallerInfo ou Quote
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         Invalid interpolated string. {0}
         Chaîne interpolée non valide. {0}
diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf
index 4c119a33d12..a13b9a27c0f 100644
--- a/src/Compiler/xlf/FSComp.txt.it.xlf
+++ b/src/Compiler/xlf/FSComp.txt.it.xlf
@@ -162,6 +162,11 @@
         Parametro di tipo noto: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         L'argomento alla posizione di indice {0} non corrisponde
@@ -172,6 +177,16 @@
         L'argomento '{0}' non corrisponde
         
       
+      
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
+        
+      
+      
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        
+      
       
         The constraints 'unmanaged' and 'not struct' are inconsistent
         The constraints 'unmanaged' and 'not struct' are inconsistent
@@ -197,6 +212,11 @@
         L'attributo di assembly '{0}' fa riferimento a un assembly '{1}' della finestra di progettazione che non è stato caricato o non esiste. L'eccezione restituita è {2} - {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         underscore dot shorthand for accessor only function
         underscore dot shorthand for accessor only function
@@ -382,6 +402,11 @@
         Interop facoltativo nullable
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         dichiarazione di tipo aperto
@@ -732,6 +757,11 @@
         Stampare le interfacce derivate di tutti i file di compilazione nei file di firma associati
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Cancellare la cache dei risultati di Gestione pacchetti
@@ -1262,6 +1292,11 @@
         Questo valore '{0}' non è una funzione e non supporta la notazione degli indici.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         La sintassi 'expr1[expr2]' è ambigua se usata come argomento. Vedere https://aka.ms/fsharp-index-notation. Se si intende eseguire l'indicizzazione o il sezionamento, è necessario usare 'expr1.[expr2]' nella posizione dell'argomento. Se si chiama una funzione con più argomenti sottoposti a corsi, aggiungere uno spazio tra di essi, ad esempio 'someFunction expr1 [expr2]'.
@@ -1367,6 +1402,11 @@
         Un tratto non può specificare argomenti optional, in, out, ParamArray, CallerInfo o Quote
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         Invalid interpolated string. {0}
         La stringa interpolata non è valida. {0}
diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf
index 1b8e87aba35..2494297b2ee 100644
--- a/src/Compiler/xlf/FSComp.txt.ja.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ja.xlf
@@ -162,6 +162,11 @@
         既知の型パラメーター: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         インデックス {0} の引数が一致しません
@@ -172,6 +177,16 @@
         引数 '{0}' が一致しません
         
       
+      
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
+        
+      
+      
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        
+      
       
         The constraints 'unmanaged' and 'not struct' are inconsistent
         The constraints 'unmanaged' and 'not struct' are inconsistent
@@ -197,6 +212,11 @@
         アセンブリ属性 '{0}' は、デザイナー アセンブリ '{1}' を参照していますが、これは読み込むことができないか、存在していません。報告された例外: {2} - {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         underscore dot shorthand for accessor only function
         underscore dot shorthand for accessor only function
@@ -382,6 +402,11 @@
         Null 許容のオプションの相互運用
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         オープン型宣言
@@ -732,6 +757,11 @@
         すべてのコンパイル ファイルの推定されたインターフェイスを関連する署名ファイルに印刷します
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         パッケージ マネージャーの結果キャッシュをクリアする
@@ -1262,6 +1292,11 @@
         値 '{0}' は関数ではなく、インデックス表記をサポートしていません。
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         構文 'expr1[expr2]' は引数として使用されている場合、あいまいです。https://aka.ms/fsharp-index-notation を参照してください。インデックス作成またはスライスを行う場合は、'expr1.[expr2]' を引数の位置に使用する必要があります。複数のカリー化された引数を持つ関数を呼び出す場合は、'expr1 [expr2]' のように間にスペースを追加します。
@@ -1367,6 +1402,11 @@
         特性では、オプションの、in 引数、out 引数、ParamArray 引数、CallerInfo 引数、または Quote 引数を指定することはできません
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         Invalid interpolated string. {0}
         補間された文字列が無効です。{0}
diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf
index 0020567546e..c9529f8312c 100644
--- a/src/Compiler/xlf/FSComp.txt.ko.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ko.xlf
@@ -162,6 +162,11 @@
         알려진 형식 매개 변수: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         인덱스 {0}의 인수가 일치하지 않습니다.
@@ -172,6 +177,16 @@
         '{0}' 인수가 일치하지 않습니다.
         
       
+      
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
+        
+      
+      
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        
+      
       
         The constraints 'unmanaged' and 'not struct' are inconsistent
         The constraints 'unmanaged' and 'not struct' are inconsistent
@@ -197,6 +212,11 @@
         '{0}' 어셈블리 특성이 로드할 수 없거나 존재하지 않는 디자이너 어셈블리'{1}'을(를) 참조합니다. 보고된 예외: {2} - {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         underscore dot shorthand for accessor only function
         underscore dot shorthand for accessor only function
@@ -382,6 +402,11 @@
         nullable 선택적 interop
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         개방형 형식 선언
@@ -732,6 +757,11 @@
         모든 컴파일 파일의 유추된 인터페이스를 관련 서명 파일로 인쇄합니다.
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         패키지 관리자 결과 캐시 지우기
@@ -1262,6 +1292,11 @@
         '{0}' 값은 함수가 아니며 인덱스 표기법을 지원하지 않습니다.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         'expr1[expr2]' 구문은 인수로 사용될 때 모호합니다. https://aka.ms/fsharp-index-notation을 참조하세요. 인덱싱이나 슬라이싱을 하려면 인수 위치에 'expr1.[expr2]'를 사용해야 합니다. 여러 개의 커리된 인수로 함수를 호출하는 경우 그 사이에 공백을 추가하세요(예: 'someFunction expr1 [expr2]').
@@ -1367,6 +1402,11 @@
         특성은 optional, in, out, ParamArray, CallerInfo, Quote 인수를 지정할 수 없습니다.
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         Invalid interpolated string. {0}
         잘못된 보간 문자열. {0}
diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf
index 05281e00c71..7d7f5baf36f 100644
--- a/src/Compiler/xlf/FSComp.txt.pl.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pl.xlf
@@ -162,6 +162,11 @@
         Parametr znanego typu: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         Argument pod indeksem {0} nie jest zgodny
@@ -172,6 +177,16 @@
         Argument „{0}” nie jest zgodny
         
       
+      
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
+        
+      
+      
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        
+      
       
         The constraints 'unmanaged' and 'not struct' are inconsistent
         The constraints 'unmanaged' and 'not struct' are inconsistent
@@ -197,6 +212,11 @@
         Atrybut zestawu „{0}” odwołuje się do zestawu projektanta „{1}”, którego nie można załadować lub który nie istnieje. Zgłoszony wyjątek: {2} — {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         underscore dot shorthand for accessor only function
         underscore dot shorthand for accessor only function
@@ -382,6 +402,11 @@
         opcjonalna międzyoperacyjność dopuszczająca wartość null
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         deklaracja typu otwartego
@@ -732,6 +757,11 @@
         Drukowanie wywnioskowanych interfejsów wszystkich plików kompilacji do skojarzonych plików sygnatur
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Wyczyść pamięć podręczną wyników menedżera pakietów
@@ -1262,6 +1292,11 @@
         Wartość elementu „{0}” nie jest funkcją i nie obsługuje notacji indeksowej.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         Składnia wyrażenia „expr1[expr2]” jest niejednoznaczna, gdy jest używana jako argument. Zobacz https://aka.ms/fsharp-index-notation. Jeśli zamierzasz indeksować lub fragmentować, to w pozycji argumentu musi być użyte wyrażenie „expr1.[expr2]”. Jeśli wywołujesz funkcję z wieloma argumentami typu curried, dodaj spację między nimi, np. „someFunction expr1 [expr2]”.
@@ -1367,6 +1402,11 @@
         Cecha nie może określać opcjonalnych argumentów in, out, ParamArray, CallerInfo lub Quote
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         Invalid interpolated string. {0}
         Nieprawidłowy ciąg interpolowany. {0}
diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
index 0eba2d9314b..8a42d71b513 100644
--- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
@@ -162,6 +162,11 @@
         Parâmetro de tipo conhecido: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         O argumento no índice {0} não corresponde
@@ -172,6 +177,16 @@
         O argumento '{0}' não corresponde
         
       
+      
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
+        
+      
+      
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        
+      
       
         The constraints 'unmanaged' and 'not struct' are inconsistent
         The constraints 'unmanaged' and 'not struct' are inconsistent
@@ -197,6 +212,11 @@
         O atributo de assembly '{0}' refere-se a um assembly de designer '{1}' que não pode ser carregado ou que não existe. A exceção relatada foi {2} – {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         underscore dot shorthand for accessor only function
         underscore dot shorthand for accessor only function
@@ -382,6 +402,11 @@
         interoperabilidade opcional anulável
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         declaração de tipo aberto
@@ -732,6 +757,11 @@
         Imprimir as interfaces inferidas de todos os arquivos de compilação para os arquivos de assinatura associados
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Limpar o cache de resultados do gerenciador de pacotes
@@ -1262,6 +1292,11 @@
         O valor '{0}' não é uma função e não dá suporte à notação de índice.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         A sintaxe '[expr1][expr2]' é ambígua quando usada como um argumento. Consulte https://aka.ms/fsharp-index-notation. Se você pretende indexar ou colocar em fatias, deve usar '(expr1).[expr2]' na posição do argumento. Se chamar uma função com vários argumentos na forma curried, adicione um espaço entre eles, por exemplo, 'someFunction [expr1] [expr2]'.
@@ -1367,6 +1402,11 @@
         Uma característica não pode especificar os argumentos optional, in, out, ParamArray, CallerInfo ou Quote
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         Invalid interpolated string. {0}
         Cadeia de caracteres interpolada inválida. {0}
diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf
index cb097a62717..7be010ce5cb 100644
--- a/src/Compiler/xlf/FSComp.txt.ru.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ru.xlf
@@ -162,6 +162,11 @@
         Известный параметр типа: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         Аргумент в индексе {0} не соответствует
@@ -172,6 +177,16 @@
         Аргумент "{0}" не соответствует
         
       
+      
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
+        
+      
+      
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        
+      
       
         The constraints 'unmanaged' and 'not struct' are inconsistent
         The constraints 'unmanaged' and 'not struct' are inconsistent
@@ -197,6 +212,11 @@
         Атрибут сборки "{0}" ссылается на сборку конструктора "{1}", которая не может быть загружена или не существует. Получено исключение: {2} — {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         underscore dot shorthand for accessor only function
         underscore dot shorthand for accessor only function
@@ -382,6 +402,11 @@
         необязательное взаимодействие, допускающее значение NULL
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         объявление открытого типа
@@ -732,6 +757,11 @@
         Печать определяемых интерфейсов всех файлов компиляции в связанные файлы подписей
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Очистка кэша результатов диспетчера пакетов
@@ -1262,6 +1292,11 @@
         Значение {0} не является функцией и не поддерживает нотацию индекса.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         Синтаксис "expr1[expr2]" неоднозначен при использовании в качестве аргумента. См. https://aka.ms/fsharp-index-notation. Если вы намереваетесь индексировать или разрезать, необходимо использовать "expr1.[expr2]" в позиции аргумента. При вызове функции с несколькими каррированными аргументами добавьте пробел между ними, например "someFunction expr1 [expr2]".
@@ -1367,6 +1402,11 @@
         Признак не может указывать необязательные аргументы in, out, ParamArray, CallerInfo или Quote
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         Invalid interpolated string. {0}
         Недопустимая интерполированная строка. {0}
diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf
index 6f7d4c805e9..805cd5378b2 100644
--- a/src/Compiler/xlf/FSComp.txt.tr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.tr.xlf
@@ -162,6 +162,11 @@
         Bilinen tür parametresi: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         {0} dizinindeki bağımsız değişken eşleşmiyor
@@ -172,6 +177,16 @@
         '{0}' bağımsız değişkeni eşleşmiyor
         
       
+      
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
+        
+      
+      
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        
+      
       
         The constraints 'unmanaged' and 'not struct' are inconsistent
         The constraints 'unmanaged' and 'not struct' are inconsistent
@@ -197,6 +212,11 @@
         '{0}' bütünleştirilmiş kod özniteliği, yüklenemeyen veya mevcut olmayan '{1}' tasarımcı bütünleştirilmiş koduna başvuruyor. Bildirilen özel durum: {2} - {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         underscore dot shorthand for accessor only function
         underscore dot shorthand for accessor only function
@@ -382,6 +402,11 @@
         null atanabilir isteğe bağlı birlikte çalışma
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         açık tür bildirimi
@@ -732,6 +757,11 @@
         Tüm derleme dosyalarının çıkarsanan arabirimlerini ilişkili imza dosyalarına yazdır
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         Paket yöneticisi sonuçları önbelleğini temizle
@@ -1262,6 +1292,11 @@
         “{0}” değeri bir işlev değildir ve dizin gösterimini desteklemez.
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         Söz dizimi “expr1[expr2]” artık dizin oluşturma için ayrılmıştır ve bağımsız değişken olarak kullanıldığında belirsizdir. https://aka.ms/fsharp-index-notation'a bakın. Dizin oluşturmayı veya dilimlemeyi düşünüyorsanız, bağımsız değişken konumunda “expr1.[expr2]” kullanmalısınız. Birden çok curry bağımsız değişkenli bir işlev çağırıyorsanız, aralarına bir boşluk ekleyin, örn. “someFunction expr1 [expr2]”.
@@ -1367,6 +1402,11 @@
         Bir nitelik optional, in, out, ParamArray, CallerInfo veya Quote bağımsız değişkenlerini belirtemiyor
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         Invalid interpolated string. {0}
         Geçersiz düz metin arasına kod eklenmiş dize. {0}
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
index 2607c85378a..150d72009fa 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
@@ -162,6 +162,11 @@
         已知类型参数: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         索引 {0} 处的参数不匹配
@@ -172,6 +177,16 @@
         参数 "{0}" 不匹配
         
       
+      
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
+        
+      
+      
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        
+      
       
         The constraints 'unmanaged' and 'not struct' are inconsistent
         The constraints 'unmanaged' and 'not struct' are inconsistent
@@ -197,6 +212,11 @@
         程序集属性“{0}”引用了无法加载或不存在的设计器程序集“{1}”。报告的异常是: {2} - {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         underscore dot shorthand for accessor only function
         underscore dot shorthand for accessor only function
@@ -382,6 +402,11 @@
         可以为 null 的可选互操作
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         开放类型声明
@@ -732,6 +757,11 @@
         将所有编译文件的推断接口打印到关联的签名文件
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         清除包管理器结果缓存
@@ -1262,6 +1292,11 @@
         值 '{0}' 不是函数,不支持索引表示法。
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         语法“expr1[expr2]”用作参数时不明确。请参阅 https://aka.ms/fsharp-index-notation。如果要索引或切片,则必须在参数位置使用“expr1.[expr2]”。如果使用多个扩充参数调用函数,请在它们之间添加空格,例如“someFunction expr1 [expr2]”。
@@ -1367,6 +1402,11 @@
         特征不能指定 option、in、out、ParamArray、CallerInfo 或 Quote 参数
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         Invalid interpolated string. {0}
         内插字符串无效。{0}
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
index bfb346cd26f..5086f043f53 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
@@ -162,6 +162,11 @@
         已知的型別參數: {0}
         
       
+      
+        The constraints 'null' and 'not null' are inconsistent
+        The constraints 'null' and 'not null' are inconsistent
+        
+      
       
         Argument at index {0} doesn't match
         位於索引 {0} 的引數不相符
@@ -172,6 +177,16 @@
         引數 '{0}' 不相符
         
       
+      
+        The type '{0}' supports 'null' but a non-null type is expected
+        The type '{0}' supports 'null' but a non-null type is expected
+        
+      
+      
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        The type '{0}' uses 'null' as a representation value but a non-null type is expected
+        
+      
       
         The constraints 'unmanaged' and 'not struct' are inconsistent
         The constraints 'unmanaged' and 'not struct' are inconsistent
@@ -197,6 +212,11 @@
         無法載入組件屬性 '{0}' 參考的設計工具組件 '{1}' 或其不存在。回報的例外狀況: {2} - {3}
         
       
+      
+        {0} for F# {1}
+        {0} for F# {1}
+        
+      
       
         underscore dot shorthand for accessor only function
         underscore dot shorthand for accessor only function
@@ -382,6 +402,11 @@
         可為 Null 的選擇性 Interop
         
       
+      
+        nullness checking
+        nullness checking
+        
+      
       
         open type declaration
         開放式類型宣告
@@ -732,6 +757,11 @@
         將所有編譯檔案的推斷介面列印至相關聯的簽章檔案
         
       
+      
+        Enable nullness declarations and checks
+        Enable nullness declarations and checks
+        
+      
       
         Clear the package manager results cache
         清除封裝管理員結果快取
@@ -1262,6 +1292,11 @@
         值 '{0}' 並非函式,不支援索引標記法。
         
       
+      
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+        
+      
       
         The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'.
         語法 'expr1[expr2]' 用作引數時不明確。請參閱 https://aka.ms/fsharp-index-notation。如果您要編製索引或切割,則必須在引數位置使用 'expr1.[expr2]'。如果要呼叫具有多個調用引數的函式,請在它們之間新增空格,例如 'someFunction expr1 [expr2]'。
@@ -1367,6 +1402,11 @@
         特徵不能指定選擇性、in、out、ParamArray、CallerInfo 或 Quote 引數
         
       
+      
+        The type '{0}' does not support a nullness qualitification.
+        The type '{0}' does not support a nullness qualitification.
+        
+      
       
         Invalid interpolated string. {0}
         插補字串無效。{0}
diff --git a/src/Compiler/xlf/FSStrings.cs.xlf b/src/Compiler/xlf/FSStrings.cs.xlf
index 4676ded7083..58e06721da2 100644
--- a/src/Compiler/xlf/FSStrings.cs.xlf
+++ b/src/Compiler/xlf/FSStrings.cs.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Neshoda typů Očekává se řazená kolekce členů o délce {0} typu\n    {1}    \nale odevzdala se řazená kolekce členů o délce {2} typu\n    {3}{4}\n
@@ -42,11 +62,21 @@
         interpolovaný řetězec (část)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
       
         keyword 'while!'
         keyword 'while!'
         
       
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Viz taky {0}.
diff --git a/src/Compiler/xlf/FSStrings.de.xlf b/src/Compiler/xlf/FSStrings.de.xlf
index 0b386bdd064..b740ff53ade 100644
--- a/src/Compiler/xlf/FSStrings.de.xlf
+++ b/src/Compiler/xlf/FSStrings.de.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Typenkonflikt. Es wurde ein Tupel der Länge {0} des Typs\n    {1}    \nerwartet, aber ein Tupel der Länge {2} des Typs\n    {3}{4}\n angegeben.
@@ -42,11 +62,21 @@
         Interpolierte Zeichenfolge (Teil)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
       
         keyword 'while!'
         keyword 'while!'
         
       
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Siehe auch "{0}".
diff --git a/src/Compiler/xlf/FSStrings.es.xlf b/src/Compiler/xlf/FSStrings.es.xlf
index a5008e7c476..755995b0cbc 100644
--- a/src/Compiler/xlf/FSStrings.es.xlf
+++ b/src/Compiler/xlf/FSStrings.es.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Error de coincidencia de tipos. Se espera una tupla de longitud {0} de tipo\n    {1}    \nperero se ha proporcionado una tupla de longitud {2} de tipo\n    {3}{4}\n
@@ -42,11 +62,21 @@
         cadena interpolada (parte)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
       
         keyword 'while!'
         keyword 'while!'
         
       
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Vea también {0}.
diff --git a/src/Compiler/xlf/FSStrings.fr.xlf b/src/Compiler/xlf/FSStrings.fr.xlf
index a8ffac1edb2..a73d049c106 100644
--- a/src/Compiler/xlf/FSStrings.fr.xlf
+++ b/src/Compiler/xlf/FSStrings.fr.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Incompatibilité de type. Tuple de longueur attendu {0} de type\n {1} \nmais tuple de longueur {2} de type\n    {3}{4}\n
@@ -42,11 +62,21 @@
         chaîne interpolée (partie)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
       
         keyword 'while!'
         keyword 'while!'
         
       
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Voir aussi {0}.
diff --git a/src/Compiler/xlf/FSStrings.it.xlf b/src/Compiler/xlf/FSStrings.it.xlf
index 9654664e86b..7568d912c32 100644
--- a/src/Compiler/xlf/FSStrings.it.xlf
+++ b/src/Compiler/xlf/FSStrings.it.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Tipo non corrispondente. È prevista una tupla di lunghezza {0} di tipo\n   {1}    \n, ma è stata specificata una tupla di lunghezza {2} di tipo\n    {3}{4}\n
@@ -42,11 +62,21 @@
         stringa interpolata (parte)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
       
         keyword 'while!'
         keyword 'while!'
         
       
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Vedere anche {0}.
diff --git a/src/Compiler/xlf/FSStrings.ja.xlf b/src/Compiler/xlf/FSStrings.ja.xlf
index d5ec4d91da6..c9642a7b238 100644
--- a/src/Compiler/xlf/FSStrings.ja.xlf
+++ b/src/Compiler/xlf/FSStrings.ja.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         型が一致しません。型の長さ {0} のタプルが必要です\n    {1}    \nただし、型の長さ {2} のタプルが指定された場合\n    {3}{4}\n
@@ -42,11 +62,21 @@
         補間された文字列 (部分)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
       
         keyword 'while!'
         keyword 'while!'
         
       
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         。{0} も参照してください。
diff --git a/src/Compiler/xlf/FSStrings.ko.xlf b/src/Compiler/xlf/FSStrings.ko.xlf
index b4ee40c250c..d02eb85f5b1 100644
--- a/src/Compiler/xlf/FSStrings.ko.xlf
+++ b/src/Compiler/xlf/FSStrings.ko.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         유형 불일치. 형식이 \n    {1}이고 길이가 {0}인 튜플이 필요합니다.    \n그러나 형식이 \n    {3}이고 길이가 {2}인 튜플이 제공되었습니다.{4}\n
@@ -42,11 +62,21 @@
         보간 문자열(부분)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
       
         keyword 'while!'
         keyword 'while!'
         
       
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         {0}도 참조하세요.
diff --git a/src/Compiler/xlf/FSStrings.pl.xlf b/src/Compiler/xlf/FSStrings.pl.xlf
index b01d8256e3e..30c77ac7915 100644
--- a/src/Compiler/xlf/FSStrings.pl.xlf
+++ b/src/Compiler/xlf/FSStrings.pl.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Niezgodność. Oczekiwano krotki o długości {0} typu\n    {1}    \nale otrzymano krotkę o długości {2} typu\n    {3}{4}\n
@@ -42,11 +62,21 @@
         ciąg interpolowany (część)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
       
         keyword 'while!'
         keyword 'while!'
         
       
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Zobacz też {0}.
diff --git a/src/Compiler/xlf/FSStrings.pt-BR.xlf b/src/Compiler/xlf/FSStrings.pt-BR.xlf
index 44b24e76174..560a3bcc9f8 100644
--- a/src/Compiler/xlf/FSStrings.pt-BR.xlf
+++ b/src/Compiler/xlf/FSStrings.pt-BR.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Tipo incompatível. Esperando uma tupla de comprimento {0} do tipo\n    {1}    \nmas recebeu uma tupla de comprimento {2} do tipo\n    {3}{4}\n
@@ -42,11 +62,21 @@
         cadeia de caracteres interpolada (parte)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
       
         keyword 'while!'
         keyword 'while!'
         
       
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Consulte também {0}.
diff --git a/src/Compiler/xlf/FSStrings.ru.xlf b/src/Compiler/xlf/FSStrings.ru.xlf
index 6d0c1b1d517..18e6978c0c7 100644
--- a/src/Compiler/xlf/FSStrings.ru.xlf
+++ b/src/Compiler/xlf/FSStrings.ru.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Несоответствие типов. Ожидается кортеж длиной {0} типа\n    {1},    \nно предоставлен кортеж длиной {2} типа\n    {3}{4}\n
@@ -42,11 +62,21 @@
         интерполированная строка (часть)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
       
         keyword 'while!'
         keyword 'while!'
         
       
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . См. также {0}.
diff --git a/src/Compiler/xlf/FSStrings.tr.xlf b/src/Compiler/xlf/FSStrings.tr.xlf
index 8758b001581..a56fa595c82 100644
--- a/src/Compiler/xlf/FSStrings.tr.xlf
+++ b/src/Compiler/xlf/FSStrings.tr.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Tür uyuşmazlığı. {0} uzunluğunda türü\n {1} \nolan bir demet bekleniyordu ancak {2} uzunluğunda türü\n    {3}{4}\nolan bir demet verildi
@@ -42,11 +62,21 @@
         düz metin arasına kod eklenmiş dize (parça)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
       
         keyword 'while!'
         keyword 'while!'
         
       
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         . Ayrıca bkz. {0}.
diff --git a/src/Compiler/xlf/FSStrings.zh-Hans.xlf b/src/Compiler/xlf/FSStrings.zh-Hans.xlf
index e21e73e60f7..cc62cbd1802 100644
--- a/src/Compiler/xlf/FSStrings.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSStrings.zh-Hans.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         类型不匹配。应为长度为 {0} 的类型的元组\n    {1}    \n但提供了长度为 {2} 的类型的元组\n    {3}{4}\n
@@ -42,11 +62,21 @@
         内插字符串(部分)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
       
         keyword 'while!'
         keyword 'while!'
         
       
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         。请参见 {0}。
diff --git a/src/Compiler/xlf/FSStrings.zh-Hant.xlf b/src/Compiler/xlf/FSStrings.zh-Hant.xlf
index 5d294f8b58a..1cb335012c3 100644
--- a/src/Compiler/xlf/FSStrings.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSStrings.zh-Hant.xlf
@@ -2,6 +2,26 @@
 
   
     
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         類型不符。必須是類型為\n    {1}    \n 的元組長度 {0},但提供的是類型為\n    {3}{4}\n 的元組長度 {2}
@@ -42,11 +62,21 @@
         插補字串 (部分)
         
       
+      
+        keyword '__notnull'
+        keyword '__notnull'
+        
+      
       
         keyword 'while!'
         keyword 'while!'
         
       
+      
+        keyword '__withnull'
+        keyword '__withnull'
+        
+      
       
         . See also {0}.
         。請參閱 {0}。
diff --git a/src/FSharp.Core/option.fs b/src/FSharp.Core/option.fs
index e44f2a8e5e9..ca3f678852d 100644
--- a/src/FSharp.Core/option.fs
+++ b/src/FSharp.Core/option.fs
@@ -344,13 +344,13 @@ module ValueOption =
         | ValueSome x -> x
 #else
     []
-    let ofObj (value: 'T __withnull) : 'T voption when 'T: not struct and 'T : __notnull  = 
+    let inline ofObj (value: 'T __withnull) : 'T voption when 'T: not struct and 'T : __notnull  = 
         match value with
         | null -> ValueNone
         | _ -> ValueSome value
 
     []
-    let toObj (value : 'T voption) : 'T __withnull when 'T: not struct (* and 'T : __notnull *) = 
+    let inline toObj (value : 'T voption) : 'T __withnull when 'T: not struct (* and 'T : __notnull *) = 
         match value with
         | ValueNone -> null
         | ValueSome x -> x

From f08b67820da2e5c0c1cf9e877f0fc9bb3d5eacd1 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Fri, 8 Sep 2023 14:01:38 +0200
Subject: [PATCH 24/59] Feature/nullness - parsing of constraints (#15753)

* Feature/nullness - parsing of constraints for:
'T: not null ....  syntax in Type argument specification
appType | NULL ...  for specifying types
---
 src/Compiler/Checking/CheckExpressions.fs     |   1 -
 src/Compiler/Checking/ConstraintSolver.fs     |   2 +-
 src/Compiler/Driver/CompilerDiagnostics.fs    |   1 +
 src/Compiler/FSStrings.resx                   |   3 +
 src/Compiler/Service/ServiceLexing.fs         |   1 +
 src/Compiler/SyntaxTree/LexFilter.fs          |  10 +-
 src/Compiler/pars.fsy                         | 177 ++++++++++--------
 src/Compiler/xlf/FSStrings.cs.xlf             |   5 +
 src/Compiler/xlf/FSStrings.de.xlf             |   5 +
 src/Compiler/xlf/FSStrings.es.xlf             |   5 +
 src/Compiler/xlf/FSStrings.fr.xlf             |   5 +
 src/Compiler/xlf/FSStrings.it.xlf             |   5 +
 src/Compiler/xlf/FSStrings.ja.xlf             |   5 +
 src/Compiler/xlf/FSStrings.ko.xlf             |   5 +
 src/Compiler/xlf/FSStrings.pl.xlf             |   5 +
 src/Compiler/xlf/FSStrings.pt-BR.xlf          |   5 +
 src/Compiler/xlf/FSStrings.ru.xlf             |   5 +
 src/Compiler/xlf/FSStrings.tr.xlf             |   5 +
 src/Compiler/xlf/FSStrings.zh-Hans.xlf        |   5 +
 src/Compiler/xlf/FSStrings.zh-Hant.xlf        |   5 +
 tests/AheadOfTime/Trimming/check.ps1          |   2 +-
 .../FSharp.Compiler.Service.Tests.fsproj      |   6 +
 tests/fsharp/typecheck/sigs/neg04.bsl         |   8 +-
 tests/fsharp/typecheck/sigs/neg119b.bsl       |   4 +-
 tests/fsharp/typecheck/sigs/neg29.bsl         |   4 +-
 tests/fsharp/typecheck/sigs/neg69.vsbsl       |   7 +-
 .../Nullness/AbstractClassProperty.fs         |   3 +
 .../Nullness/AbstractClassProperty.fs.bsl     |  60 ++++++
 .../SyntaxTree/Nullness/DuCaseStringOrNull.fs |   1 +
 .../Nullness/DuCaseStringOrNull.fs.bsl        |  37 ++++
 .../Nullness/DuCaseTuplePrecedence.fs         |   1 +
 .../Nullness/DuCaseTuplePrecedence.fs.bsl     |  43 +++++
 .../data/SyntaxTree/Nullness/ExplicitField.fs |   4 +
 .../SyntaxTree/Nullness/ExplicitField.fs.bsl  |  30 +++
 .../FunctionArgAsPatternWithNullCase.fs       |   1 +
 .../FunctionArgAsPatternWithNullCase.fs.bsl   |  46 +++++
 .../GenericFunctionReturnTypeNotStructNull.fs |   1 +
 ...ericFunctionReturnTypeNotStructNull.fs.bsl |  43 +++++
 .../Nullness/GenericFunctionTyparNotNull.fs   |   1 +
 .../GenericFunctionTyparNotNull.fs.bsl        |  36 ++++
 .../Nullness/GenericFunctionTyparNull.fs      |   1 +
 .../Nullness/GenericFunctionTyparNull.fs.bsl  |  36 ++++
 .../SyntaxTree/Nullness/GenericTypeNotNull.fs |   1 +
 .../Nullness/GenericTypeNotNull.fs.bsl        |  27 +++
 .../GenericTypeNotNullAndOtherConstraint.fs   |   1 +
 ...enericTypeNotNullAndOtherConstraint.fs.bsl |  29 +++
 ...tructAndOtherConstraint-I_am_Still_Sane.fs |   1 +
 ...tAndOtherConstraint-I_am_Still_Sane.fs.bsl |  34 ++++
 .../SyntaxTree/Nullness/GenericTypeNull.fs    |   1 +
 .../Nullness/GenericTypeNull.fs.bsl           |  27 +++
 ...enericTypeOtherConstraintAndThenNotNull.fs |   1 +
 ...icTypeOtherConstraintAndThenNotNull.fs.bsl |  29 +++
 .../data/SyntaxTree/Nullness/IntListOrNull.fs |   1 +
 .../SyntaxTree/Nullness/IntListOrNull.fs.bsl  |  37 ++++
 .../Nullness/IntListOrNullOrNullOrNull.fs     |   1 +
 .../Nullness/IntListOrNullOrNullOrNull.fs.bsl |  39 ++++
 .../SyntaxTree/Nullness/MatchWithTypeCast.fs  |   2 +
 .../Nullness/MatchWithTypeCast.fs.bsl         |  23 +++
 .../Nullness/MatchWithTypeCastParens.fs       |   2 +
 .../Nullness/MatchWithTypeCastParens.fs.bsl   |  23 +++
 ...chWithTypeCastParensAndSeparateNullCase.fs |   2 +
 ...thTypeCastParensAndSeparateNullCase.fs.bsl |  26 +++
 .../Nullness/NullAnnotatedExpression.fs       |   1 +
 .../Nullness/NullAnnotatedExpression.fs.bsl   |  68 +++++++
 .../RegressionAnnotatedInlinePatternMatch.fs  |   2 +
 ...gressionAnnotatedInlinePatternMatch.fs.bsl |  29 +++
 .../Nullness/RegressionChoiceType.fs          |   7 +
 .../Nullness/RegressionChoiceType.fs.bsl      |  53 ++++++
 .../SyntaxTree/Nullness/RegressionListType.fs |   3 +
 .../Nullness/RegressionListType.fs.bsl        |  63 +++++++
 .../Nullness/RegressionOneLinerOptionType.fs  |   1 +
 .../RegressionOneLinerOptionType.fs.bsl       |  37 ++++
 .../Nullness/RegressionOptionType.fs          |   3 +
 .../Nullness/RegressionOptionType.fs.bsl      |  64 +++++++
 .../Nullness/RegressionOrPattern.fs           |   3 +
 .../Nullness/RegressionOrPattern.fs.bsl       |  40 ++++
 .../Nullness/RegressionResultType.fs          |   7 +
 .../Nullness/RegressionResultType.fs.bsl      |  54 ++++++
 .../Nullness/SignatureInAbstractMember.fs     |   2 +
 .../Nullness/SignatureInAbstractMember.fs.bsl |  60 ++++++
 .../data/SyntaxTree/Nullness/StringOrNull.fs  |   1 +
 .../SyntaxTree/Nullness/StringOrNull.fs.bsl   |  31 +++
 .../Nullness/StringOrNullInFunctionArg.fs     |   1 +
 .../Nullness/StringOrNullInFunctionArg.fs.bsl |  36 ++++
 .../TypeAbbreviationAddingWithNull.fs         |   1 +
 .../TypeAbbreviationAddingWithNull.fs.bsl     |  24 +++
 86 files changed, 1440 insertions(+), 93 deletions(-)
 create mode 100644 tests/service/data/SyntaxTree/Nullness/AbstractClassProperty.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/AbstractClassProperty.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/DuCaseStringOrNull.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/DuCaseStringOrNull.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/DuCaseTuplePrecedence.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/DuCaseTuplePrecedence.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/ExplicitField.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/ExplicitField.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/FunctionArgAsPatternWithNullCase.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/FunctionArgAsPatternWithNullCase.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericFunctionReturnTypeNotStructNull.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericFunctionReturnTypeNotStructNull.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNotNull.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNotNull.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNull.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNull.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericTypeNotNull.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericTypeNotNull.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericTypeNotNullAndOtherConstraint.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericTypeNotNullAndOtherConstraint.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericTypeNotStructAndOtherConstraint-I_am_Still_Sane.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericTypeNotStructAndOtherConstraint-I_am_Still_Sane.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericTypeNull.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericTypeNull.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericTypeOtherConstraintAndThenNotNull.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/GenericTypeOtherConstraintAndThenNotNull.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/IntListOrNull.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/IntListOrNull.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/IntListOrNullOrNullOrNull.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/IntListOrNullOrNullOrNull.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/MatchWithTypeCast.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/MatchWithTypeCast.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParens.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParens.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParensAndSeparateNullCase.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParensAndSeparateNullCase.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/RegressionAnnotatedInlinePatternMatch.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/RegressionAnnotatedInlinePatternMatch.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/RegressionChoiceType.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/RegressionChoiceType.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/RegressionListType.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/RegressionListType.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/RegressionOneLinerOptionType.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/RegressionOneLinerOptionType.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/RegressionOptionType.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/RegressionOptionType.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/RegressionOrPattern.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/RegressionOrPattern.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/RegressionResultType.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/RegressionResultType.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/SignatureInAbstractMember.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/SignatureInAbstractMember.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/StringOrNull.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/StringOrNull.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/StringOrNullInFunctionArg.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/StringOrNullInFunctionArg.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Nullness/TypeAbbreviationAddingWithNull.fs
 create mode 100644 tests/service/data/SyntaxTree/Nullness/TypeAbbreviationAddingWithNull.fs.bsl

diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs
index 6f6aa0d6b70..08f3104203b 100644
--- a/src/Compiler/Checking/CheckExpressions.fs
+++ b/src/Compiler/Checking/CheckExpressions.fs
@@ -4658,7 +4658,6 @@ and TcIntersectionConstraint (cenv: cenv) env newOk checkConstraints occ tpenv s
         ) tpenv
 
     let tpTy = tp.AsType KnownAmbivalentToNull // TODO: NULLNESS
-
     tpTy, tpenv
 
 and TcTypeStaticConstant kindOpt tpenv c m =
diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs
index 2f8915d6846..d624abf78c5 100644
--- a/src/Compiler/Checking/ConstraintSolver.fs
+++ b/src/Compiler/Checking/ConstraintSolver.fs
@@ -4091,4 +4091,4 @@ let IsApplicableMethApprox g amap m (minfo: MethInfo) availObjTy =
             |> CommitOperationResult
         | _ -> true
     else
-        true
+        true
\ No newline at end of file
diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs
index 970bfd17624..34e202d5018 100644
--- a/src/Compiler/Driver/CompilerDiagnostics.fs
+++ b/src/Compiler/Driver/CompilerDiagnostics.fs
@@ -1289,6 +1289,7 @@ type Exception with
                 | Parser.TOKEN_INTERP_STRING_END -> SR.GetString("Parser.TOKEN.INTERP.STRING.END")
                 | Parser.TOKEN_WITHNULL__ -> SR.GetString("Parser.TOKEN.WITHNULL__")
                 | Parser.TOKEN_NOTNULL__ -> SR.GetString("Parser.TOKEN.NOTNULL__")
+                | Parser.TOKEN_BAR_JUST_BEFORE_NULL -> SR.GetString("Parser.TOKEN.BAR_JUST_BEFORE_NULL")
                 | unknown ->
                     let result = sprintf "unknown token tag %+A" unknown
                     Debug.Assert(false, result)
diff --git a/src/Compiler/FSStrings.resx b/src/Compiler/FSStrings.resx
index ffcf00b5784..3af0391078c 100644
--- a/src/Compiler/FSStrings.resx
+++ b/src/Compiler/FSStrings.resx
@@ -426,6 +426,9 @@
   
     symbol '|}'
   
+  
+    symbol '|' (directly before 'null')
+  
   
     symbol '>}'
   
diff --git a/src/Compiler/Service/ServiceLexing.fs b/src/Compiler/Service/ServiceLexing.fs
index 22fb8682f5a..c8f4797021c 100644
--- a/src/Compiler/Service/ServiceLexing.fs
+++ b/src/Compiler/Service/ServiceLexing.fs
@@ -395,6 +395,7 @@ module internal TokenClassifications =
         | MAYBENULL__
         | NOTNULL__
         | WITHNULL__
+        | BAR_JUST_BEFORE_NULL
         | TYPE_COMING_SOON
         | TYPE_IS_HERE
         | MODULE_COMING_SOON
diff --git a/src/Compiler/SyntaxTree/LexFilter.fs b/src/Compiler/SyntaxTree/LexFilter.fs
index cd7e16c9b21..d17c27d7329 100644
--- a/src/Compiler/SyntaxTree/LexFilter.fs
+++ b/src/Compiler/SyntaxTree/LexFilter.fs
@@ -1123,10 +1123,11 @@ type LexFilterImpl (
                     //      fx
                     //      fx
                     //      fx
-                    //      fx
-                    //      fx
+                    //      fx
+                    //      fx
+                    //      fx
                     | DEFAULT | COLON | COLON_GREATER | STRUCT | NULL | DELEGATE | AND | WHEN | AMP
-                    | NOTNULL__ | MAYBENULL__ | WITHNULL__
+                    | NOTNULL__ | MAYBENULL__ | WITHNULL__ | BAR_JUST_BEFORE_NULL
                     | DOT_DOT
                     | NEW
                     | LBRACE_BAR
@@ -2438,6 +2439,9 @@ type LexFilterImpl (
             pool.Return tokenTup
             hwTokenFetch useBlockRule
 
+        | BAR, _ when (lexbuf.SupportsFeature(LanguageFeature.NullnessChecking) && match peekNextToken() with NULL -> true | _ -> false) ->
+            returnToken tokenLexbufState BAR_JUST_BEFORE_NULL            
+
         // Ordinary tokens start a vanilla block
         | _, CtxtSeqBlock _ :: _ ->
             pushCtxt tokenTup (CtxtVanilla(tokenStartPos, isLongIdentEquals token))
diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy
index f6dff65edd1..7ff2fe76510 100644
--- a/src/Compiler/pars.fsy
+++ b/src/Compiler/pars.fsy
@@ -89,7 +89,7 @@ let parse_error_rich = Some(fun (ctxt: ParseErrorContext<_>) ->
 %token GREATER_RBRACK STRUCT SIG
 %token STATIC MEMBER CLASS ABSTRACT OVERRIDE DEFAULT CONSTRUCTOR INHERIT
 %token EXTERN VOID PUBLIC PRIVATE INTERNAL GLOBAL
-%token MAYBENULL__ NOTNULL__ WITHNULL__
+%token MAYBENULL__ NOTNULL__ WITHNULL__ BAR_JUST_BEFORE_NULL
 
 /* for parser 'escape hatch' out of expression context without consuming the 'recover' token */
 %token TYPE_COMING_SOON TYPE_IS_HERE MODULE_COMING_SOON MODULE_IS_HERE
@@ -256,6 +256,7 @@ let parse_error_rich = Some(fun (ctxt: ParseErrorContext<_>) ->
 /* Lower than "if a then b" */
 %left prec_then_before
 %nonassoc prec_then_if
+%nonassoc BAR_JUST_BEFORE_NULL
 %left BAR
 
 %right SEMICOLON prec_semiexpr_sep OBLOCKSEP
@@ -971,11 +972,11 @@ classMemberSpfn:
        let trivia: SynMemberSigMemberTrivia = { GetSetKeywords = getSetRangeOpt }
        SynMemberSig.Member(valSpfn, flags, mWhole, trivia) }
 
-  | opt_attributes opt_access interfaceMember appType
+  | opt_attributes opt_access interfaceMember appTypeWithoutNull
      { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2))
        SynMemberSig.Interface($4, unionRanges (rhs parseState 3) ($4).Range) }
 
-  | opt_attributes opt_access INHERIT appType
+  | opt_attributes opt_access INHERIT appTypeWithoutNull
      { if Option.isSome $2 then errorR (Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier (), rhs parseState 2))
        SynMemberSig.Inherit($4, unionRanges (rhs parseState 1) $4.Range) }
 
@@ -1356,7 +1357,7 @@ openDecl:
       { let mOpen = rhs parseState 1
         SynOpenDeclTarget.ModuleOrNamespace(SynLongIdent([], [], []), mOpen.EndRange), mOpen }
 
-  | OPEN typeKeyword appType
+  | OPEN typeKeyword appTypeWithoutNull
       { let mOpen = rhs parseState 1
         let mPath = $3.Range
         SynOpenDeclTarget.Type($3, mPath), unionRanges mOpen mPath }
@@ -1603,12 +1604,9 @@ tyconDefn:
        let (tcDefRepr, mWith, members) = $8 nameRange
        let (SynComponentInfo(_, _, _, lid, _, _, _, _)) = $1
        let mEquals = rhs parseState 7
-
        // Gets the XML doc comments prior to the implicit constructor
        let xmlDoc = grabXmlDoc (parseState, $2, 2)
-
        let m = match lid with [] -> rhs parseState 1 | _ -> rangeOfLid lid
-
        let memberCtorPattern =
            spats |> Option.map (fun spats ->
                SynMemberDefn.ImplicitCtor(vis, $2, spats, Option.bind snd az, xmlDoc, m, { AsKeyword = Option.map fst az })
@@ -1636,14 +1634,11 @@ tyconDefn:
              | Some(_, Some id) ->
                  reportParseErrorAt (rhs parseState 6) (FSComp.SR.tcLetAndDoRequiresImplicitConstructionSequence ())
              | _ -> ()
-
              tcDefRepr
-
        let declRange = unionRanges (rhs parseState 1) tcDefRepr.Range
        let mWhole = (declRange, members)
                     ||> unionRangeWithListBy (fun (mem: SynMemberDefn) -> mem.Range)
                     |> unionRangeWithXmlDoc xmlDoc
-
        fun leadingKeyword ->
            let trivia: SynTypeDefnTrivia = { LeadingKeyword = leadingKeyword; EqualsRange = Some mEquals; WithKeyword = mWith }
            SynTypeDefn($1, tcDefRepr, members, memberCtorPattern, mWhole, trivia) }
@@ -1660,7 +1655,6 @@ tyconDefn:
            | Some spats, _, _ ->
                let memberCtorPattern = SynMemberDefn.ImplicitCtor(vis, $2, spats, Option.bind snd az, xmlDoc, m, { AsKeyword = Option.map fst az })
                [memberCtorPattern], unionRanges mName memberCtorPattern.Range
-
            | _, _, Some(mAs, asId) ->
                let mAs =
                    asId |> Option.map (fun id ->
@@ -1668,12 +1662,9 @@ tyconDefn:
                        id.idRange
                    )
                    |> Option.defaultValue mAs
-
                [], unionRanges mName mAs
-
            | _, Some vis, _ ->
                [], unionRanges mName vis.Range
-
            | _ ->
                [], mName
 
@@ -1681,7 +1672,6 @@ tyconDefn:
            let trivia = { SynTypeDefnTrivia.Zero with LeadingKeyword = leadingKeyword }
            SynTypeDefn($1, SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.None(mName), mName), members, None, mWhole, trivia) }
 
-
 /* The right-hand-side of a type definition */
 tyconDefnRhsBlock:
   /* This rule allows members to be given for record and union types in the #light syntax */
@@ -1998,7 +1988,7 @@ classDefnMember:
 
         [SynMemberDefn.Member(binding, mWhole)] }
 
-  | opt_attributes opt_access interfaceMember appType opt_interfaceImplDefn
+  | opt_attributes opt_access interfaceMember appTypeWithoutNull opt_interfaceImplDefn
      { if not (isNil $1) then errorR(Error(FSComp.SR.parsAttributesAreNotPermittedOnInterfaceImplementations(), rhs parseState 1))
        if Option.isSome $2 then errorR(Error(FSComp.SR.parsInterfacesHaveSameVisibilityAsEnclosingType(), rhs parseState 3))
        let mWithKwd, members, mWhole =
@@ -2389,12 +2379,12 @@ tyconDefnOrSpfnSimpleRepr:
   | opt_attributes opt_access path LQUOTE STRING recover
      { errorR(Error(FSComp.SR.parsUnexpectedQuotationOperatorInTypeAliasDidYouMeanVerbatimString(), rhs parseState 4))
        SynTypeDefnSimpleRepr.TypeAbbrev(ParserDetail.ErrorRecovery, SynType.LongIdent($3), unionRanges (rhs parseState 1) $3.Range) }
-
-  /* A type abbreviation */
+							
+  /* A type abbreviation  */
   | opt_attributes opt_access typ
      { if not (isNil $1) then errorR(Error(FSComp.SR.parsAttributesIllegalHere(), rhs parseState 1))
        if Option.isSome $2 then errorR(Error(FSComp.SR.parsTypeAbbreviationsCannotHaveVisibilityDeclarations(), rhs parseState 2))
-       SynTypeDefnSimpleRepr.TypeAbbrev(ParserDetail.Ok, $3, unionRanges (rhs parseState 1) $3.Range) }
+       SynTypeDefnSimpleRepr.TypeAbbrev(ParserDetail.Ok, $3, unionRanges (rhs parseState 1) $3.Range) }  
 
   /* A union type definition */
   | opt_attributes opt_access unionTypeRepr
@@ -2607,6 +2597,13 @@ typeConstraint:
   | typar COLON NOTNULL__
       { SynTypeConstraint.WhereTyparNotSupportsNull($1, lhs parseState) }
 
+  | typar COLON IDENT NULL
+      { if $3 <> "not" then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier($3 + " (2)"))  
+        SynTypeConstraint.WhereTyparNotSupportsNull($1, lhs parseState) }
+
+  | typar COLON NOTNULL__
+      { SynTypeConstraint.WhereTyparNotSupportsNull($1, lhs parseState) }
+
   | typar COLON LPAREN classMemberSpfn rparen
      { let tp = $1
        SynTypeConstraint.WhereTyparSupportsMember(SynType.Var(tp, tp.Range), $4, lhs parseState) }
@@ -2634,16 +2631,16 @@ typeConstraint:
        | "unmanaged" -> SynTypeConstraint.WhereTyparIsUnmanaged($1, lhs parseState)
        | nm -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier(nm + " (4)")) }
 
-  | appType
+  | appTypeWithoutNull
      { SynTypeConstraint.WhereSelfConstrained($1, lhs parseState) }
 
 typeAlts:
-  | typeAlts OR appType
+  | typeAlts OR appTypeWithoutNull
      { let mOr = rhs parseState 2
        let m = unionRanges $1.Range $3.Range
        SynType.Or($1, $3, m, { OrKeyword = mOr }) }
 
-  | appType
+  | appTypeWithoutNull
      { $1 }
 
 /* The core of a union type definition */
@@ -2753,6 +2750,13 @@ firstUnionCaseDecl:
         let mDecl = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc
         Choice2Of2(SynUnionCase([], SynIdent($1, None), SynUnionCaseKind.Fields $3, xmlDoc, None, mDecl, trivia)) }
 
+  | unionCaseName COLON topType 
+      { if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyWarning(lhs parseState)
+        let trivia: SynUnionCaseTrivia = { BarRange = None }
+        let xmlDoc = grabXmlDoc (parseState, [], 1)
+        let mDecl = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc
+        Choice2Of2(SynUnionCase([], $1, SynUnionCaseKind.FullType $3, xmlDoc, None, mDecl, trivia)) }
+
   | ident OF recover
       { let trivia: SynUnionCaseTrivia = { BarRange = None }
         let xmlDoc = grabXmlDoc (parseState, [], 1)
@@ -2784,12 +2788,12 @@ unionCaseReprElements:
      { [$1] }
 
 unionCaseReprElement:
-  | ident COLON appType
+  | ident COLON appTypeNullableInParens
      { let xmlDoc = grabXmlDoc(parseState, [], 1)
        let mWhole = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc
        mkSynNamedField ($1, $3, xmlDoc, mWhole) }
 
-  | appType
+  | appTypeNullableInParens
      { let xmlDoc = grabXmlDoc(parseState, [], 1)
        mkSynAnonField ($1, xmlDoc) }
 
@@ -3114,6 +3118,9 @@ cType:
   | cType WITHNULL__
     { SynType.WithNull($1, false, lhs parseState) }
 
+  | cType BAR_JUST_BEFORE_NULL NULL
+    { SynType.WithNull($1, false, lhs parseState) }
+
   | cType AMP
      { let m = lhs parseState
        SynType.App(SynType.LongIdent(SynLongIdent([ident("byref", m)], [], [ Some(IdentTrivia.OriginalNotation "&") ])), None, [$1], [], None, true, m) }
@@ -3440,12 +3447,18 @@ simplePatterns:
         let simplePats, _ = SimplePatsOfPat parseState.SynArgNameGenerator pat
         simplePats }
 
+barCanBeRightBeforeNull:
+  | BAR
+      {  }
+  | BAR_JUST_BEFORE_NULL
+      {  }
+
 
 headBindingPattern:
-  | headBindingPattern AS constrPattern
+  | headBindingPattern AS constrPattern %prec AS
       { SynPat.As($1, $3, rhs2 parseState 1 3) }
 
-  | headBindingPattern BAR headBindingPattern
+  | headBindingPattern barCanBeRightBeforeNull headBindingPattern %prec   BAR
       { let mBar = rhs parseState 2
         SynPat.Or($1, $3, rhs2 parseState 1 3, { BarRange = mBar }) }
 
@@ -3716,10 +3729,10 @@ parenPatternBody:
 /* duplicating the entire expression grammar, or making a fairly severe breaking change */
 /* to the language. */
 parenPattern:
-  | parenPattern AS constrPattern
+  | parenPattern AS constrPattern %prec  AS
       { SynPat.As($1, $3, rhs2 parseState 1 3) }
 
-  | parenPattern BAR parenPattern
+  | parenPattern barCanBeRightBeforeNull parenPattern %prec  BAR
       { let mBar = rhs parseState 2
         SynPat.Or($1, $3, rhs2 parseState 1 3, { BarRange = mBar }) }
 
@@ -4615,11 +4628,11 @@ withPatternClauses:
   | patternClauses
       { $1 None }
 
-  | BAR patternClauses
+  | barCanBeRightBeforeNull patternClauses
       { let mBar = rhs parseState 1 |> Some
         $2 mBar }
 
-  | BAR error
+  | barCanBeRightBeforeNull error
       { // silent recovery
         let mLast = rhs parseState 1
         [], mLast }
@@ -4643,7 +4656,7 @@ patternClauses:
        fun mBar ->
            [SynMatchClause(pat, guard, resultExpr, m, DebugPointAtTarget.Yes, { ArrowRange = Some mArrow; BarRange = mBar })], mLast }
 
-  | patternAndGuard patternResult BAR patternClauses
+  | patternAndGuard patternResult barCanBeRightBeforeNull patternClauses
      { let pat, guard = $1
        let mArrow, resultExpr = $2
        let mNextBar = rhs parseState 3 |> Some
@@ -4652,7 +4665,7 @@ patternClauses:
        fun mBar ->
            (SynMatchClause(pat, guard, resultExpr, m, DebugPointAtTarget.Yes, { ArrowRange = Some mArrow; BarRange = mBar }) :: clauses), mLast }
 
-  | patternAndGuard error BAR patternClauses
+  | patternAndGuard error barCanBeRightBeforeNull patternClauses
      { let pat, guard = $1
        let mNextBar = rhs parseState 3 |> Some
        let clauses, mLast = $4 mNextBar
@@ -4661,7 +4674,7 @@ patternClauses:
        fun _mBar ->
            (SynMatchClause(pat, guard, arbExpr ("patternClauses1", m.EndRange), m, DebugPointAtTarget.Yes, SynMatchClauseTrivia.Zero) :: clauses), mLast }
 
-  | patternAndGuard patternResult BAR recover
+  | patternAndGuard patternResult barCanBeRightBeforeNull recover
      { let pat, guard = $1
        let mArrow, resultExpr = $2
        let mLast = rhs parseState 3
@@ -5198,9 +5211,10 @@ typars:
         SynType.Paren($2, m) }
 
 typarAlts:
-  | typarAlts OR appType
+  | typarAlts OR appTypeCanBeNullable
       { let mOr = rhs parseState 2
-        let m = unionRanges $1.Range $3.Range
+        let appType : SynType = $3
+        let m = unionRanges $1.Range appType.Range
         SynType.Or($1, $3, m, { OrKeyword = mOr }) }
 
   | typar
@@ -5533,7 +5547,7 @@ opt_objExprInterfaces:
      { (* silent recovery *) $2 }
 
 objExprInterface:
-  | interfaceMember appType opt_objExprBindings opt_declEnd opt_OBLOCKSEP
+  | interfaceMember appTypeWithoutNull opt_objExprBindings opt_declEnd opt_OBLOCKSEP
     { let mWithKwd, bindings, members = $3
       let m =
           match List.tryLast members with
@@ -5755,14 +5769,14 @@ topTupleTypeElements:
        [ SynTupleTypeSegment.Type t, Some argInfo ] }
 
 topAppType:
-  | attributes appType COLON appType
+  | attributes appTypeCanBeNullable COLON appTypeCanBeNullable
       { match $2 with
         | SynType.LongIdent(SynLongIdent([id], _, _)) ->
             let m = unionRanges (rhs parseState 1) $4.Range
             SynType.SignatureParameter($1, false, Some id, $4, m), SynArgInfo($1, false, Some id)
         | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsSyntaxErrorInLabeledType()) }
 
-  | attributes appType COLON recover
+  | attributes appTypeCanBeNullable COLON recover
       { match $2 with
         | SynType.LongIdent(SynLongIdent([id], _, _)) ->
             let mColon = rhs parseState 2
@@ -5771,7 +5785,7 @@ topAppType:
             SynType.SignatureParameter($1, false, Some id, ty, m), SynArgInfo($1, false, Some id)
         | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsSyntaxErrorInLabeledType()) }
 
-  | attributes QMARK ident COLON appType
+  | attributes QMARK ident COLON appTypeCanBeNullable
       { let m = unionRanges (rhs parseState 1) $5.Range
         SynType.SignatureParameter($1, true, Some $3, $5, m), SynArgInfo($1, true, Some $3) }
 
@@ -5781,18 +5795,18 @@ topAppType:
         let ty = SynType.FromParseError(mColon.EndRange)
         SynType.SignatureParameter($1, true, Some $3, ty, m), SynArgInfo($1, true, Some $3) }
 
-  | attributes appType
+  | attributes appTypeCanBeNullable
       { let m = unionRanges (rhs parseState 1) $2.Range
         SynType.SignatureParameter($1, false, None, $2, m), SynArgInfo($1, false, None) }
 
-  | appType COLON appType
+  | appTypeCanBeNullable COLON appTypeCanBeNullable
       { match $1 with
         | SynType.LongIdent(SynLongIdent([id], _, _)) ->
             let m = unionRanges (rhs parseState 1) $3.Range
             SynType.SignatureParameter([], false, Some id, $3, m), SynArgInfo([], false, Some id)
         | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsSyntaxErrorInLabeledType()) }
 
-  | appType COLON recover
+  | appTypeCanBeNullable COLON recover
       { match $1 with
         | SynType.LongIdent(SynLongIdent([id], _, _)) ->
             let mColon = rhs parseState 2
@@ -5801,7 +5815,7 @@ topAppType:
             SynType.SignatureParameter([], false, Some id, ty, m), SynArgInfo([], false, Some id)
         | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsSyntaxErrorInLabeledType()) }
 
-  | QMARK ident COLON appType
+  | QMARK ident COLON appTypeCanBeNullable
       { let m = unionRanges (rhs parseState 1) $4.Range
         SynType.SignatureParameter([], true, Some $2, $4, m), SynArgInfo([], true, Some $2) }
 
@@ -5811,22 +5825,22 @@ topAppType:
         let ty = SynType.FromParseError(mColon.EndRange)
         SynType.SignatureParameter([], true, Some $2, ty, m), SynArgInfo([], true, Some $2) }
 
-  | appType
+  | appTypeCanBeNullable
      { $1, SynArgInfo([], false, None) }
 
 /* Grammar rule meant for recovery scenarios */
 /* For example in unionCaseReprElement where function type is not allowed */
 invalidUseOfAppTypeFunction:
-  | appType RARROW invalidUseOfAppTypeFunction
+  | appTypeWithoutNull RARROW invalidUseOfAppTypeFunction
      { let mArrow = rhs parseState 2
        let m = unionRanges (rhs2 parseState 1 2) $3.Range
        SynType.Fun($1, $3, m, { ArrowRange = mArrow }) }
-  | appType RARROW recover
+  | appTypeWithoutNull RARROW recover
      { let mArrow = rhs parseState 2
        let ty = SynType.FromParseError(mArrow.EndRange)
        let m = rhs2 parseState 1 2
        SynType.Fun($1, ty, m, { ArrowRange = mArrow }) }
-  | appType RARROW RARROW invalidUseOfAppTypeFunction
+  | appTypeWithoutNull RARROW RARROW invalidUseOfAppTypeFunction
      { let mArrow1 = rhs parseState 2
        let mArrow2 = rhs parseState 3
        reportParseErrorAt mArrow2 (FSComp.SR.parsExpectingType ())
@@ -5834,7 +5848,7 @@ invalidUseOfAppTypeFunction:
        let m1 = unionRanges $1.Range $4.Range
        let m2 = unionRanges mArrow2 $4.Range
        SynType.Fun($1, SynType.Fun(ty, $4, m2, { ArrowRange = mArrow2 }), m1, { ArrowRange = mArrow1 }) }
-  | appType RARROW appType
+  | appTypeWithoutNull RARROW appTypeWithoutNull
      { let mArrow = rhs parseState 2
        let m = rhs2 parseState 1 3
        SynType.Fun($1, $3, m, { ArrowRange = mArrow }) }
@@ -5870,12 +5884,12 @@ typEOF:
 
 
 tupleType:
-  | appType STAR tupleOrQuotTypeElements
+  | appTypeCanBeNullable STAR tupleOrQuotTypeElements
       { let mStar = rhs parseState 2
         let path = SynTupleTypeSegment.Type $1 :: SynTupleTypeSegment.Star mStar :: $3
         mkSynTypeTuple path }
 
-  | appType STAR recover
+  | appTypeCanBeNullable STAR recover
       { let mStar = rhs parseState 2
         let ty = SynType.FromParseError(mStar.EndRange)
         let path = [SynTupleTypeSegment.Type $1; SynTupleTypeSegment.Star mStar; SynTupleTypeSegment.Type ty]
@@ -5901,28 +5915,28 @@ tupleType:
         let path = [SynTupleTypeSegment.Slash mSlash; SynTupleTypeSegment.Type ty]
         mkSynTypeTuple path }
 
-  | appType INFIX_STAR_DIV_MOD_OP tupleOrQuotTypeElements
+  | appTypeCanBeNullable INFIX_STAR_DIV_MOD_OP tupleOrQuotTypeElements
       { if $2 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedInfixOperator())
         let mSlash = rhs parseState 2
         let path = SynTupleTypeSegment.Type $1 :: SynTupleTypeSegment.Slash mSlash :: $3
         mkSynTypeTuple path }
 
-  | appType INFIX_STAR_DIV_MOD_OP recover
+  | appTypeCanBeNullable INFIX_STAR_DIV_MOD_OP recover
       { if $2 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedInfixOperator ())
         let mSlash = rhs parseState 2
         let ty = SynType.FromParseError(mSlash.EndRange)
         let path = [SynTupleTypeSegment.Type $1; SynTupleTypeSegment.Slash mSlash; SynTupleTypeSegment.Type ty]
         mkSynTypeTuple path }
 
-  | appType %prec prec_tuptyp_prefix
+  | appTypeCanBeNullable %prec prec_tuptyp_prefix
       { $1 }
 
 tupleOrQuotTypeElements:
-  | appType STAR tupleOrQuotTypeElements
+  | appTypeCanBeNullable STAR tupleOrQuotTypeElements
       { let mStar = rhs parseState 2
         SynTupleTypeSegment.Type $1 :: SynTupleTypeSegment.Star mStar :: $3 }
 
-  | appType STAR recover
+  | appTypeCanBeNullable STAR recover
       { let mStar = rhs parseState 2
         let ty = SynType.FromParseError(mStar.EndRange)
         [SynTupleTypeSegment.Type $1; SynTupleTypeSegment.Star mStar; SynTupleTypeSegment.Type ty] }
@@ -5933,12 +5947,12 @@ tupleOrQuotTypeElements:
         reportParseErrorAt mStar (FSComp.SR.parsExpectingType ())
         SynTupleTypeSegment.Type ty :: SynTupleTypeSegment.Star mStar :: $2 }
 
-  | appType INFIX_STAR_DIV_MOD_OP tupleOrQuotTypeElements
+  | appTypeCanBeNullable INFIX_STAR_DIV_MOD_OP tupleOrQuotTypeElements
       { if $2 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedInfixOperator ())
         let mSlash = rhs parseState 2
         SynTupleTypeSegment.Type $1 :: SynTupleTypeSegment.Slash mSlash :: $3 }
 
-  | appType INFIX_STAR_DIV_MOD_OP recover
+  | appTypeCanBeNullable INFIX_STAR_DIV_MOD_OP recover
       { if $2 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedInfixOperator ())
         let mSlash = rhs parseState 2
         let ty = SynType.FromParseError(mSlash.EndRange)
@@ -5951,7 +5965,7 @@ tupleOrQuotTypeElements:
         reportParseErrorAt mSlash (FSComp.SR.parsExpectingType ())
         SynTupleTypeSegment.Type ty :: SynTupleTypeSegment.Slash mSlash :: $2 }
 
-  | appType %prec prec_tuptyptail_prefix
+  | appTypeCanBeNullable %prec prec_tuptyptail_prefix
       { [ SynTupleTypeSegment.Type $1 ] }
 
 intersectionType:
@@ -5983,25 +5997,40 @@ appTypeConPower:
   | appTypeCon
     { $1 }
 
-appType:
-  | appType MAYBENULL__
+appTypeCanBeNullable:
+  | appTypeWithoutNull BAR_JUST_BEFORE_NULL NULL
+    { SynType.WithNull($1, false, lhs parseState) }
+
+  | appTypeWithoutNull
+    { $1 }
+
+appTypeNullableInParens:
+  | appTypeWithoutNull
+    { $1 }
+
+  | LPAREN appTypeCanBeNullable rparen
+    { SynType.Paren($2, lhs parseState) }
+
+appTypeWithoutNull:
+  | appTypeWithoutNull MAYBENULL__
     { SynType.WithNull($1, true, lhs parseState) }
 
-  | appType WITHNULL__
+  | appTypeWithoutNull WITHNULL__
     { SynType.WithNull($1, false, lhs parseState) }
 
 /*
-  | appType QMARK
+  | appTypeWithoutNull QMARK
     { SynType.WithNull($1, false, lhs parseState) }
 */
 
-  | appType arrayTypeSuffix
+  | appTypeWithoutNull arrayTypeSuffix
+
       { SynType.Array($2, $1, lhs parseState) }
 
-  | appType HIGH_PRECEDENCE_BRACK_APP arrayTypeSuffix /* only HPA for "name[]" allowed here */
+  | appTypeWithoutNull HIGH_PRECEDENCE_BRACK_APP arrayTypeSuffix /* only HPA for "name[]" allowed here */
       { SynType.Array($3, $1, lhs parseState) }
 
-  | appType appTypeConPower
+  | appTypeWithoutNull appTypeConPower
       /* note: use "rhs parseState 1" to deal with parens in "(int) list" */
       { SynType.App($2, None, [$1], [], None, true, unionRanges (rhs parseState 1) $2.Range) }
 
@@ -6202,24 +6231,24 @@ atomType:
      { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen ())
        SynType.Paren($2, lhs parseState) }
 
-  | STRUCT LPAREN appType STAR tupleOrQuotTypeElements rparen
+  | STRUCT LPAREN appTypeCanBeNullable STAR tupleOrQuotTypeElements rparen
     { let mStar = rhs parseState 4
       let path = SynTupleTypeSegment.Type $3 :: SynTupleTypeSegment.Star mStar :: $5
       let m = rhs2 parseState 1 6
       SynType.Tuple(true, path, m) }
 
-  | STRUCT LPAREN appType STAR tupleOrQuotTypeElements recover
+  | STRUCT LPAREN appTypeCanBeNullable STAR tupleOrQuotTypeElements recover
     { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnmatchedParen())
       let mStar = rhs parseState 4
       let path = SynTupleTypeSegment.Type $3 :: SynTupleTypeSegment.Star mStar :: $5
       let m = rhs2 parseState 1 5
       SynType.Tuple(true, path, m) }
 
-  | STRUCT LPAREN appType STAR recover
+  | STRUCT LPAREN appTypeCanBeNullable STAR recover
     { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnmatchedParen())
       SynType.Anon(lhs parseState) }
 
-  | STRUCT LPAREN appType recover
+  | STRUCT LPAREN appTypeCanBeNullable recover
     { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnmatchedParen())
       SynType.Anon(lhs parseState) }
 
@@ -6666,12 +6695,6 @@ deprecated_opt_equals:
   | EQUALS { deprecatedWithError (FSComp.SR.parsNoEqualShouldFollowNamespace()) (lhs parseState); () }
   | /* EMPTY */ { }
 
-opt_equals:
-  | EQUALS
-      { let mEquals = rhs parseState 1
-        Some mEquals }
-  | /* EMPTY */ { None }
-
 opt_OBLOCKSEP:
   | OBLOCKSEP { }
   | /* EMPTY */ { }
@@ -6684,10 +6707,6 @@ opt_rec:
   | REC { true }
   | /* EMPTY */ { false }
 
-opt_bar:
-  | BAR { }
-  | /* EMPTY */ { }
-
 opt_inline:
   | INLINE { Some(rhs parseState 1) }
   | /* EMPTY */ { None }
diff --git a/src/Compiler/xlf/FSStrings.cs.xlf b/src/Compiler/xlf/FSStrings.cs.xlf
index 58e06721da2..0ca74e1ad6f 100644
--- a/src/Compiler/xlf/FSStrings.cs.xlf
+++ b/src/Compiler/xlf/FSStrings.cs.xlf
@@ -37,6 +37,11 @@
         Případy sjednocení s malými písmeny jsou povolené jenom při použití atributu RequireQualifiedAccess.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         symbol ..^
diff --git a/src/Compiler/xlf/FSStrings.de.xlf b/src/Compiler/xlf/FSStrings.de.xlf
index b740ff53ade..5bb910c0b93 100644
--- a/src/Compiler/xlf/FSStrings.de.xlf
+++ b/src/Compiler/xlf/FSStrings.de.xlf
@@ -37,6 +37,11 @@
         Diskriminierte Union-Fälle in Kleinbuchstaben sind nur zulässig, wenn das RequireQualifiedAccess-Attribut verwendet wird.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         Symbol "..^"
diff --git a/src/Compiler/xlf/FSStrings.es.xlf b/src/Compiler/xlf/FSStrings.es.xlf
index 755995b0cbc..f930cc3130e 100644
--- a/src/Compiler/xlf/FSStrings.es.xlf
+++ b/src/Compiler/xlf/FSStrings.es.xlf
@@ -37,6 +37,11 @@
         Los casos de unión discriminada en minúsculas solo se permiten cuando se usa el atributo RequireQualifiedAccess
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         símbolo "..^"
diff --git a/src/Compiler/xlf/FSStrings.fr.xlf b/src/Compiler/xlf/FSStrings.fr.xlf
index a73d049c106..ee90304b65d 100644
--- a/src/Compiler/xlf/FSStrings.fr.xlf
+++ b/src/Compiler/xlf/FSStrings.fr.xlf
@@ -37,6 +37,11 @@
         Les cas d’union discriminée en minuscules sont uniquement autorisés lors de l’utilisation de l’attribut RequireQualifiedAccess.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         symbole '..^'
diff --git a/src/Compiler/xlf/FSStrings.it.xlf b/src/Compiler/xlf/FSStrings.it.xlf
index 7568d912c32..d533fcf3383 100644
--- a/src/Compiler/xlf/FSStrings.it.xlf
+++ b/src/Compiler/xlf/FSStrings.it.xlf
@@ -37,6 +37,11 @@
         I casi di unione discriminati minuscoli sono consentiti solo quando si usa l'attributo RequireQualifiedAccess
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         simbolo '..^'
diff --git a/src/Compiler/xlf/FSStrings.ja.xlf b/src/Compiler/xlf/FSStrings.ja.xlf
index c9642a7b238..3627feb9bf7 100644
--- a/src/Compiler/xlf/FSStrings.ja.xlf
+++ b/src/Compiler/xlf/FSStrings.ja.xlf
@@ -37,6 +37,11 @@
         小文字で区別される和集合のケースは、RequireQualifiedAccess 属性を使用する場合にのみ許可されます
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         シンボル '..^'
diff --git a/src/Compiler/xlf/FSStrings.ko.xlf b/src/Compiler/xlf/FSStrings.ko.xlf
index d02eb85f5b1..fdb8589dc36 100644
--- a/src/Compiler/xlf/FSStrings.ko.xlf
+++ b/src/Compiler/xlf/FSStrings.ko.xlf
@@ -37,6 +37,11 @@
         소문자로 구분된 공용 구조체 케이스는 RequireQualifiedAccess 특성을 사용하는 경우에만 허용됩니다.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         기호 '..^'
diff --git a/src/Compiler/xlf/FSStrings.pl.xlf b/src/Compiler/xlf/FSStrings.pl.xlf
index 30c77ac7915..612b025b4bc 100644
--- a/src/Compiler/xlf/FSStrings.pl.xlf
+++ b/src/Compiler/xlf/FSStrings.pl.xlf
@@ -37,6 +37,11 @@
         Przypadki unii z dyskryminatorem z małymi literami są dozwolone tylko w przypadku używania atrybutu RequireQualifiedAccess
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         symbol „..^”
diff --git a/src/Compiler/xlf/FSStrings.pt-BR.xlf b/src/Compiler/xlf/FSStrings.pt-BR.xlf
index 560a3bcc9f8..a4f48b46735 100644
--- a/src/Compiler/xlf/FSStrings.pt-BR.xlf
+++ b/src/Compiler/xlf/FSStrings.pt-BR.xlf
@@ -37,6 +37,11 @@
         Os casos de união discriminados em letras minúsculas só são permitidos ao usar o atributo RequireQualifiedAccess
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         símbolo '..^'
diff --git a/src/Compiler/xlf/FSStrings.ru.xlf b/src/Compiler/xlf/FSStrings.ru.xlf
index 18e6978c0c7..1c8e749697d 100644
--- a/src/Compiler/xlf/FSStrings.ru.xlf
+++ b/src/Compiler/xlf/FSStrings.ru.xlf
@@ -37,6 +37,11 @@
         Размеченные в нижнем регистре случаи объединения разрешены только при использовании атрибута RequireQualifiedAccess
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         символ "..^"
diff --git a/src/Compiler/xlf/FSStrings.tr.xlf b/src/Compiler/xlf/FSStrings.tr.xlf
index a56fa595c82..3a7631b488c 100644
--- a/src/Compiler/xlf/FSStrings.tr.xlf
+++ b/src/Compiler/xlf/FSStrings.tr.xlf
@@ -37,6 +37,11 @@
         Küçük harf ayrımlı birleşim durumlarına yalnızca RequireQualifiedAccess özniteliği kullanılırken izin verilir
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         '..^' sembolü
diff --git a/src/Compiler/xlf/FSStrings.zh-Hans.xlf b/src/Compiler/xlf/FSStrings.zh-Hans.xlf
index cc62cbd1802..baec1f056fe 100644
--- a/src/Compiler/xlf/FSStrings.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSStrings.zh-Hans.xlf
@@ -37,6 +37,11 @@
         仅当使用 RequireQualifiedAccess 属性时才允许区分小写的联合事例
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         符号 "..^"
diff --git a/src/Compiler/xlf/FSStrings.zh-Hant.xlf b/src/Compiler/xlf/FSStrings.zh-Hant.xlf
index 1cb335012c3..cd9bd4799a0 100644
--- a/src/Compiler/xlf/FSStrings.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSStrings.zh-Hant.xlf
@@ -37,6 +37,11 @@
         只有在使用 RequireQualifiedAccess 屬性時,才允許小寫區分聯結案例
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         符號 '..^'
diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index 834c0b0aacc..bf5f29bc306 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -47,4 +47,4 @@ CheckTrim -root "SelfContained_Trimming_Test" -tfm "net472" -outputfile "FSharp.
 CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net472" -outputfile "StaticLinkedFSharpCore_Trimming_Test.exe" -expected_len -1
 
 # Check net7.0 trimmed assemblies
-CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net7.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 8821248
+CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net7.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 8822272
diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj
index b761ced68fd..5d902c1671a 100644
--- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj
+++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj
@@ -94,6 +94,12 @@
     
   
 
+	
+		
+			SyntaxTreeTestSource\%(RecursiveDir)\%(Extension)\%(Filename)%(Extension)
+		
+	
+
   
     
     
diff --git a/tests/fsharp/typecheck/sigs/neg04.bsl b/tests/fsharp/typecheck/sigs/neg04.bsl
index 88ae776c8ca..f444d1f6ca9 100644
--- a/tests/fsharp/typecheck/sigs/neg04.bsl
+++ b/tests/fsharp/typecheck/sigs/neg04.bsl
@@ -30,10 +30,16 @@ neg04.fs(47,30,47,51): typecheck error FS0001: Type mismatch. Expecting a
     ''a seq -> 'n'    
 but given a
     ''o list -> 'p'    
-The type ''a seq' does not match the type ''n list'
+The type ''a list' does not match the type ''b seq'
 
 neg04.fs(47,49,47,51): typecheck error FS0784: This numeric literal requires that a module 'NumericLiteralN' defining functions FromZero, FromOne, FromInt32, FromInt64 and FromString be in scope
 
+neg04.fs(47,30,47,51): typecheck error FS0001: Type mismatch. Expecting a
+    ''a seq -> 'n'    
+but given a
+    ''o list -> 'p'    
+The type ''a list' does not match the type ''c seq'
+
 neg04.fs(61,25,61,40): typecheck error FS0001: This expression was expected to have type
     'ClassType1'    
 but here has type
diff --git a/tests/fsharp/typecheck/sigs/neg119b.bsl b/tests/fsharp/typecheck/sigs/neg119b.bsl
index 259e2585998..414486b9017 100644
--- a/tests/fsharp/typecheck/sigs/neg119b.bsl
+++ b/tests/fsharp/typecheck/sigs/neg119b.bsl
@@ -6,7 +6,7 @@ Known return type: ((int -> int -> int) -> obj)
 Known type parameters: < obj , Applicatives.Ap >
 
 Available overloads:
+ - static member Applicatives.Ap.Return: 'a seq * Ap: Applicatives.Ap -> ('a -> 'a seq) // Argument at index 1 doesn't match
  - static member Applicatives.Ap.Return: ('r -> 'a) * Ap: Applicatives.Ap -> (('a -> 'r -> 'a2) -> 'a3 -> 'a -> 'r -> 'a2) // Argument at index 1 doesn't match
  - static member Applicatives.Ap.Return: System.Tuple<'a> * Ap: Applicatives.Ap -> ('a -> System.Tuple<'a>) // Argument at index 1 doesn't match
- - static member Applicatives.Ap.Return: r: ^R * obj -> ('a1 -> ^R) when ^R: (static member Return: 'a1 -> ^R) // Argument 'r' doesn't match
- - static member Applicatives.Ap.Return: seq<'a> * Ap: Applicatives.Ap -> ('a -> seq<'a>) // Argument at index 1 doesn't match Consider adding further type constraints
+ - static member Applicatives.Ap.Return: r: ^R * obj -> ('a1 -> ^R) when ^R: (static member Return: 'a1 -> ^R) // Argument 'r' doesn't match Consider adding further type constraints
diff --git a/tests/fsharp/typecheck/sigs/neg29.bsl b/tests/fsharp/typecheck/sigs/neg29.bsl
index dd2d49ffda1..5f75bb8cdb0 100644
--- a/tests/fsharp/typecheck/sigs/neg29.bsl
+++ b/tests/fsharp/typecheck/sigs/neg29.bsl
@@ -1,8 +1,8 @@
 
 neg29.fs(5,19,6,16): parse error FS0010: Incomplete structured construct at or before this point in type name. Expected '>' or other token.
 
-neg29.fs(9,1,9,1): parse error FS0010: Incomplete structured construct at or before this point in implementation file
-
 neg29.fs(6,19,6,20): parse error FS0010: Unexpected symbol '(' in expression
 
 neg29.fs(6,18,6,19): parse error FS3156: Unexpected token '>' or incomplete expression
+
+neg29.fs(9,1,9,1): parse error FS0010: Incomplete structured construct at or before this point in implementation file
diff --git a/tests/fsharp/typecheck/sigs/neg69.vsbsl b/tests/fsharp/typecheck/sigs/neg69.vsbsl
index 1a0ddb7e009..45b72ad0d8f 100644
--- a/tests/fsharp/typecheck/sigs/neg69.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg69.vsbsl
@@ -1,6 +1,3 @@
-neg69.fsx(87,6,87,12): typecheck error FS0912: This declaration element is not permitted in an augmentation
-
-neg69.fsx(87,6,87,12): typecheck error FS0929: This type requires a definition
 
 neg69.fsx(88,43,88,44): parse error FS1241: Expected type argument or static argument
 
@@ -67,3 +64,7 @@ neg69.fsx(212,1,212,4): parse error FS0058: Possible incorrect indentation: this
 neg69.fsx(221,1,221,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (212:1). Try indenting this token further or using standard formatting conventions.
 
 neg69.fsx(242,1,242,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (221:1). Try indenting this token further or using standard formatting conventions.
+
+neg69.fsx(87,6,87,12): typecheck error FS0929: This type requires a definition
+
+neg69.fsx(87,6,87,12): typecheck error FS0912: This declaration element is not permitted in an augmentation
diff --git a/tests/service/data/SyntaxTree/Nullness/AbstractClassProperty.fs b/tests/service/data/SyntaxTree/Nullness/AbstractClassProperty.fs
new file mode 100644
index 00000000000..a11725eb01b
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/AbstractClassProperty.fs
@@ -0,0 +1,3 @@
+[]
+type AbstractBase() =
+   abstract Property1 : string | null with get, set
diff --git a/tests/service/data/SyntaxTree/Nullness/AbstractClassProperty.fs.bsl b/tests/service/data/SyntaxTree/Nullness/AbstractClassProperty.fs.bsl
new file mode 100644
index 00000000000..2bc15f69175
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/AbstractClassProperty.fs.bsl
@@ -0,0 +1,60 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/AbstractClassProperty.fs", false,
+      QualifiedNameOfFile AbstractClassProperty, [], [],
+      [SynModuleOrNamespace
+         ([AbstractClassProperty], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([{ Attributes =
+                         [{ TypeName =
+                             SynLongIdent ([AbstractClass], [], [None])
+                            ArgExpr = Const (Unit, (1,2--1,15))
+                            Target = None
+                            AppliesToGetterAndSetter = false
+                            Range = (1,2--1,15) }]
+                        Range = (1,0--1,17) }], None, [], [AbstractBase],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (2,5--2,17)),
+                  ObjectModel
+                    (Unspecified,
+                     [ImplicitCtor
+                        (None, [], SimplePats ([], [], (2,17--2,19)), None,
+                         PreXmlDoc ((2,17), FSharp.Compiler.Xml.XmlDocCollector),
+                         (2,5--2,17), { AsKeyword = None });
+                      AbstractSlot
+                        (SynValSig
+                           ([], SynIdent (Property1, None),
+                            SynValTyparDecls (None, true),
+                            WithNull
+                              (LongIdent (SynLongIdent ([string], [], [None])),
+                               false, (3,24--3,37)),
+                            SynValInfo ([], SynArgInfo ([], false, None)), false,
+                            false,
+                            PreXmlDoc ((3,3), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, None, (3,3--3,51),
+                            { LeadingKeyword = Abstract (3,3--3,11)
+                              InlineKeyword = None
+                              WithKeyword = Some (3,38--3,42)
+                              EqualsRange = None }),
+                         { IsInstance = true
+                           IsDispatchSlot = true
+                           IsOverrideOrExplicitImpl = false
+                           IsFinal = false
+                           GetterOrSetterIsCompilerGenerated = false
+                           MemberKind = PropertyGetSet }, (3,3--3,51),
+                         { GetSetKeywords =
+                            Some (GetSet ((3,43--3,46), (3,48--3,51))) })],
+                     (3,3--3,51)), [],
+                  Some
+                    (ImplicitCtor
+                       (None, [], SimplePats ([], [], (2,17--2,19)), None,
+                        PreXmlDoc ((2,17), FSharp.Compiler.Xml.XmlDocCollector),
+                        (2,5--2,17), { AsKeyword = None })), (1,0--3,51),
+                  { LeadingKeyword = Type (2,0--2,4)
+                    EqualsRange = Some (2,20--2,21)
+                    WithKeyword = None })], (1,0--3,51))], PreXmlDocEmpty, [],
+          None, (1,0--4,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/DuCaseStringOrNull.fs b/tests/service/data/SyntaxTree/Nullness/DuCaseStringOrNull.fs
new file mode 100644
index 00000000000..6f1f90d780a
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/DuCaseStringOrNull.fs
@@ -0,0 +1 @@
+type DU = MyCase of (string | null)
diff --git a/tests/service/data/SyntaxTree/Nullness/DuCaseStringOrNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/DuCaseStringOrNull.fs.bsl
new file mode 100644
index 00000000000..ba57735a1a8
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/DuCaseStringOrNull.fs.bsl
@@ -0,0 +1,37 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/DuCaseStringOrNull.fs", false,
+      QualifiedNameOfFile DuCaseStringOrNull, [], [],
+      [SynModuleOrNamespace
+         ([DuCaseStringOrNull], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [DU],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (1,5--1,7)),
+                  Simple
+                    (Union
+                       (None,
+                        [SynUnionCase
+                           ([], SynIdent (MyCase, None),
+                            Fields
+                              [SynField
+                                 ([], false, None,
+                                  Paren
+                                    (WithNull
+                                       (LongIdent
+                                          (SynLongIdent ([string], [], [None])),
+                                        false, (1,21--1,34)), (1,20--1,35)),
+                                  false,
+                                  PreXmlDoc ((1,20), FSharp.Compiler.Xml.XmlDocCollector),
+                                  None, (1,20--1,35), { LeadingKeyword = None })],
+                            PreXmlDoc ((1,10), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (1,10--1,35), { BarRange = None })],
+                        (1,10--1,35)), (1,10--1,35)), [], None, (1,5--1,35),
+                  { LeadingKeyword = Type (1,0--1,4)
+                    EqualsRange = Some (1,8--1,9)
+                    WithKeyword = None })], (1,0--1,35))], PreXmlDocEmpty, [],
+          None, (1,0--2,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/DuCaseTuplePrecedence.fs b/tests/service/data/SyntaxTree/Nullness/DuCaseTuplePrecedence.fs
new file mode 100644
index 00000000000..dda36337883
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/DuCaseTuplePrecedence.fs
@@ -0,0 +1 @@
+type DU = MyCase of (string | null) * int
diff --git a/tests/service/data/SyntaxTree/Nullness/DuCaseTuplePrecedence.fs.bsl b/tests/service/data/SyntaxTree/Nullness/DuCaseTuplePrecedence.fs.bsl
new file mode 100644
index 00000000000..379722c41b2
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/DuCaseTuplePrecedence.fs.bsl
@@ -0,0 +1,43 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/DuCaseTuplePrecedence.fs", false,
+      QualifiedNameOfFile DuCaseTuplePrecedence, [], [],
+      [SynModuleOrNamespace
+         ([DuCaseTuplePrecedence], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [DU],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (1,5--1,7)),
+                  Simple
+                    (Union
+                       (None,
+                        [SynUnionCase
+                           ([], SynIdent (MyCase, None),
+                            Fields
+                              [SynField
+                                 ([], false, None,
+                                  Paren
+                                    (WithNull
+                                       (LongIdent
+                                          (SynLongIdent ([string], [], [None])),
+                                        false, (1,21--1,34)), (1,20--1,35)),
+                                  false,
+                                  PreXmlDoc ((1,20), FSharp.Compiler.Xml.XmlDocCollector),
+                                  None, (1,20--1,35), { LeadingKeyword = None });
+                               SynField
+                                 ([], false, None,
+                                  LongIdent (SynLongIdent ([int], [], [None])),
+                                  false,
+                                  PreXmlDoc ((1,38), FSharp.Compiler.Xml.XmlDocCollector),
+                                  None, (1,38--1,41), { LeadingKeyword = None })],
+                            PreXmlDoc ((1,10), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (1,10--1,41), { BarRange = None })],
+                        (1,10--1,41)), (1,10--1,41)), [], None, (1,5--1,41),
+                  { LeadingKeyword = Type (1,0--1,4)
+                    EqualsRange = Some (1,8--1,9)
+                    WithKeyword = None })], (1,0--1,41))], PreXmlDocEmpty, [],
+          None, (1,0--2,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/ExplicitField.fs b/tests/service/data/SyntaxTree/Nullness/ExplicitField.fs
new file mode 100644
index 00000000000..fd93ac6b9f5
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/ExplicitField.fs
@@ -0,0 +1,4 @@
+type MyStruct =
+    struct
+        val mutable myString : string | null
+    end
diff --git a/tests/service/data/SyntaxTree/Nullness/ExplicitField.fs.bsl b/tests/service/data/SyntaxTree/Nullness/ExplicitField.fs.bsl
new file mode 100644
index 00000000000..b06e92d77eb
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/ExplicitField.fs.bsl
@@ -0,0 +1,30 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/ExplicitField.fs", false,
+      QualifiedNameOfFile ExplicitField, [], [],
+      [SynModuleOrNamespace
+         ([ExplicitField], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [MyStruct],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (1,5--1,13)),
+                  ObjectModel
+                    (Struct,
+                     [ValField
+                        (SynField
+                           ([], false, Some myString,
+                            WithNull
+                              (LongIdent (SynLongIdent ([string], [], [None])),
+                               false, (3,31--3,44)), true,
+                            PreXmlDoc ((3,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (3,20--3,44),
+                            { LeadingKeyword = Some (Val (3,8--3,11)) }),
+                         (3,8--3,44))], (2,4--4,7)), [], None, (1,5--4,7),
+                  { LeadingKeyword = Type (1,0--1,4)
+                    EqualsRange = Some (1,14--1,15)
+                    WithKeyword = None })], (1,0--4,7))], PreXmlDocEmpty, [],
+          None, (1,0--5,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/FunctionArgAsPatternWithNullCase.fs b/tests/service/data/SyntaxTree/Nullness/FunctionArgAsPatternWithNullCase.fs
new file mode 100644
index 00000000000..5cb343224f6
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/FunctionArgAsPatternWithNullCase.fs
@@ -0,0 +1 @@
+let myFunc ("abc" | "" : string | null | "123") = 15
diff --git a/tests/service/data/SyntaxTree/Nullness/FunctionArgAsPatternWithNullCase.fs.bsl b/tests/service/data/SyntaxTree/Nullness/FunctionArgAsPatternWithNullCase.fs.bsl
new file mode 100644
index 00000000000..5a519d0f7e5
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/FunctionArgAsPatternWithNullCase.fs.bsl
@@ -0,0 +1,46 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/FunctionArgAsPatternWithNullCase.fs", false,
+      QualifiedNameOfFile FunctionArgAsPatternWithNullCase, [], [],
+      [SynModuleOrNamespace
+         ([FunctionArgAsPatternWithNullCase], false, AnonModule,
+          [Let
+             (false,
+              [SynBinding
+                 (None, Normal, false, false, [],
+                  PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                  SynValData
+                    (None,
+                     SynValInfo
+                       ([[SynArgInfo ([], false, None)]],
+                        SynArgInfo ([], false, None)), None, None),
+                  LongIdent
+                    (SynLongIdent ([myFunc], [], [None]), None, None,
+                     Pats
+                       [Paren
+                          (Or
+                             (Or
+                                (Const
+                                   (String ("abc", Regular, (1,12--1,17)),
+                                    (1,12--1,17)),
+                                 Typed
+                                   (Const
+                                      (String ("", Regular, (1,20--1,22)),
+                                       (1,20--1,22)),
+                                    WithNull
+                                      (LongIdent
+                                         (SynLongIdent ([string], [], [None])),
+                                       false, (1,25--1,38)), (1,20--1,38)),
+                                 (1,12--1,38), { BarRange = (1,18--1,19) }),
+                              Const
+                                (String ("123", Regular, (1,41--1,46)),
+                                 (1,41--1,46)), (1,12--1,46),
+                              { BarRange = (1,39--1,40) }), (1,11--1,47))], None,
+                     (1,4--1,47)), None, Const (Int32 15, (1,50--1,52)),
+                  (1,4--1,47), NoneAtLet, { LeadingKeyword = Let (1,0--1,3)
+                                            InlineKeyword = None
+                                            EqualsRange = Some (1,48--1,49) })],
+              (1,0--1,52))], PreXmlDocEmpty, [], None, (1,0--2,0),
+          { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericFunctionReturnTypeNotStructNull.fs b/tests/service/data/SyntaxTree/Nullness/GenericFunctionReturnTypeNotStructNull.fs
new file mode 100644
index 00000000000..ea4694fc5e8
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericFunctionReturnTypeNotStructNull.fs
@@ -0,0 +1 @@
+let myFunc() : 'T when 'T : not struct and 'T:null = null
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericFunctionReturnTypeNotStructNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/GenericFunctionReturnTypeNotStructNull.fs.bsl
new file mode 100644
index 00000000000..a3a42b1fb1f
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericFunctionReturnTypeNotStructNull.fs.bsl
@@ -0,0 +1,43 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/GenericFunctionReturnTypeNotStructNull.fs", false,
+      QualifiedNameOfFile GenericFunctionReturnTypeNotStructNull, [], [],
+      [SynModuleOrNamespace
+         ([GenericFunctionReturnTypeNotStructNull], false, AnonModule,
+          [Let
+             (false,
+              [SynBinding
+                 (None, Normal, false, false, [],
+                  PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                  SynValData
+                    (None, SynValInfo ([[]], SynArgInfo ([], false, None)), None,
+                     None),
+                  LongIdent
+                    (SynLongIdent ([myFunc], [], [None]), None, None,
+                     Pats [Paren (Const (Unit, (1,10--1,12)), (1,10--1,12))],
+                     None, (1,4--1,12)),
+                  Some
+                    (SynBindingReturnInfo
+                       (WithGlobalConstraints
+                          (Var (SynTypar (T, None, false), (1,15--1,17)),
+                           [WhereTyparIsReferenceType
+                              (SynTypar (T, None, false), (1,23--1,38));
+                            WhereTyparSupportsNull
+                              (SynTypar (T, None, false), (1,43--1,50))],
+                           (1,15--1,50)), (1,15--1,50), [],
+                        { ColonRange = Some (1,13--1,14) })),
+                  Typed
+                    (Null (1,53--1,57),
+                     WithGlobalConstraints
+                       (Var (SynTypar (T, None, false), (1,15--1,17)),
+                        [WhereTyparIsReferenceType
+                           (SynTypar (T, None, false), (1,23--1,38));
+                         WhereTyparSupportsNull
+                           (SynTypar (T, None, false), (1,43--1,50))],
+                        (1,15--1,50)), (1,53--1,57)), (1,4--1,12), NoneAtLet,
+                  { LeadingKeyword = Let (1,0--1,3)
+                    InlineKeyword = None
+                    EqualsRange = Some (1,51--1,52) })], (1,0--1,57))],
+          PreXmlDocEmpty, [], None, (1,0--2,0), { LeadingKeyword = None })],
+      (true, true), { ConditionalDirectives = []
+                      CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNotNull.fs b/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNotNull.fs
new file mode 100644
index 00000000000..9f80e8f8ac2
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNotNull.fs
@@ -0,0 +1 @@
+let myFunc (x: 'T when 'T: not null) = 42
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNotNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNotNull.fs.bsl
new file mode 100644
index 00000000000..e648c231c86
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNotNull.fs.bsl
@@ -0,0 +1,36 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/GenericFunctionTyparNotNull.fs", false,
+      QualifiedNameOfFile GenericFunctionTyparNotNull, [], [],
+      [SynModuleOrNamespace
+         ([GenericFunctionTyparNotNull], false, AnonModule,
+          [Let
+             (false,
+              [SynBinding
+                 (None, Normal, false, false, [],
+                  PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                  SynValData
+                    (None,
+                     SynValInfo
+                       ([[SynArgInfo ([], false, Some x)]],
+                        SynArgInfo ([], false, None)), None, None),
+                  LongIdent
+                    (SynLongIdent ([myFunc], [], [None]), None, None,
+                     Pats
+                       [Paren
+                          (Typed
+                             (Named
+                                (SynIdent (x, None), false, None, (1,12--1,13)),
+                              WithGlobalConstraints
+                                (Var (SynTypar (T, None, false), (1,15--1,17)),
+                                 [WhereTyparNotSupportsNull
+                                    (SynTypar (T, None, false), (1,23--1,35))],
+                                 (1,15--1,35)), (1,12--1,35)), (1,11--1,36))],
+                     None, (1,4--1,36)), None, Const (Int32 42, (1,39--1,41)),
+                  (1,4--1,36), NoneAtLet, { LeadingKeyword = Let (1,0--1,3)
+                                            InlineKeyword = None
+                                            EqualsRange = Some (1,37--1,38) })],
+              (1,0--1,41))], PreXmlDocEmpty, [], None, (1,0--2,0),
+          { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNull.fs b/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNull.fs
new file mode 100644
index 00000000000..712e2b94c49
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNull.fs
@@ -0,0 +1 @@
+let myFunc (x: 'T when 'T: null) = 42
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNull.fs.bsl
new file mode 100644
index 00000000000..cf50c657f30
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNull.fs.bsl
@@ -0,0 +1,36 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/GenericFunctionTyparNull.fs", false,
+      QualifiedNameOfFile GenericFunctionTyparNull, [], [],
+      [SynModuleOrNamespace
+         ([GenericFunctionTyparNull], false, AnonModule,
+          [Let
+             (false,
+              [SynBinding
+                 (None, Normal, false, false, [],
+                  PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                  SynValData
+                    (None,
+                     SynValInfo
+                       ([[SynArgInfo ([], false, Some x)]],
+                        SynArgInfo ([], false, None)), None, None),
+                  LongIdent
+                    (SynLongIdent ([myFunc], [], [None]), None, None,
+                     Pats
+                       [Paren
+                          (Typed
+                             (Named
+                                (SynIdent (x, None), false, None, (1,12--1,13)),
+                              WithGlobalConstraints
+                                (Var (SynTypar (T, None, false), (1,15--1,17)),
+                                 [WhereTyparSupportsNull
+                                    (SynTypar (T, None, false), (1,23--1,31))],
+                                 (1,15--1,31)), (1,12--1,31)), (1,11--1,32))],
+                     None, (1,4--1,32)), None, Const (Int32 42, (1,35--1,37)),
+                  (1,4--1,32), NoneAtLet, { LeadingKeyword = Let (1,0--1,3)
+                                            InlineKeyword = None
+                                            EqualsRange = Some (1,33--1,34) })],
+              (1,0--1,37))], PreXmlDocEmpty, [], None, (1,0--2,0),
+          { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericTypeNotNull.fs b/tests/service/data/SyntaxTree/Nullness/GenericTypeNotNull.fs
new file mode 100644
index 00000000000..220b9e370b9
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericTypeNotNull.fs
@@ -0,0 +1 @@
+type C<'T when 'T: not null> = class end
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericTypeNotNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/GenericTypeNotNull.fs.bsl
new file mode 100644
index 00000000000..e874ec38674
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericTypeNotNull.fs.bsl
@@ -0,0 +1,27 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/GenericTypeNotNull.fs", false,
+      QualifiedNameOfFile GenericTypeNotNull, [], [],
+      [SynModuleOrNamespace
+         ([GenericTypeNotNull], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([],
+                     Some
+                       (PostfixList
+                          ([SynTyparDecl
+                              ([], SynTypar (T, None, false), [],
+                               { AmpersandRanges = [] })],
+                           [WhereTyparNotSupportsNull
+                              (SynTypar (T, None, false), (1,15--1,27))],
+                           (1,6--1,28))), [], [C],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     true, None, (1,5--1,6)),
+                  ObjectModel (Class, [], (1,31--1,40)), [], None, (1,5--1,40),
+                  { LeadingKeyword = Type (1,0--1,4)
+                    EqualsRange = Some (1,29--1,30)
+                    WithKeyword = None })], (1,0--1,40))], PreXmlDocEmpty, [],
+          None, (1,0--2,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericTypeNotNullAndOtherConstraint.fs b/tests/service/data/SyntaxTree/Nullness/GenericTypeNotNullAndOtherConstraint.fs
new file mode 100644
index 00000000000..71d3333c057
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericTypeNotNullAndOtherConstraint.fs
@@ -0,0 +1 @@
+type C<'T when 'T: not null and 'T:equality> = class end
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericTypeNotNullAndOtherConstraint.fs.bsl b/tests/service/data/SyntaxTree/Nullness/GenericTypeNotNullAndOtherConstraint.fs.bsl
new file mode 100644
index 00000000000..7a53c3be066
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericTypeNotNullAndOtherConstraint.fs.bsl
@@ -0,0 +1,29 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/GenericTypeNotNullAndOtherConstraint.fs", false,
+      QualifiedNameOfFile GenericTypeNotNullAndOtherConstraint, [], [],
+      [SynModuleOrNamespace
+         ([GenericTypeNotNullAndOtherConstraint], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([],
+                     Some
+                       (PostfixList
+                          ([SynTyparDecl
+                              ([], SynTypar (T, None, false), [],
+                               { AmpersandRanges = [] })],
+                           [WhereTyparNotSupportsNull
+                              (SynTypar (T, None, false), (1,15--1,27));
+                            WhereTyparIsEquatable
+                              (SynTypar (T, None, false), (1,32--1,43))],
+                           (1,6--1,44))), [], [C],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     true, None, (1,5--1,6)),
+                  ObjectModel (Class, [], (1,47--1,56)), [], None, (1,5--1,56),
+                  { LeadingKeyword = Type (1,0--1,4)
+                    EqualsRange = Some (1,45--1,46)
+                    WithKeyword = None })], (1,0--1,56))], PreXmlDocEmpty, [],
+          None, (1,0--2,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericTypeNotStructAndOtherConstraint-I_am_Still_Sane.fs b/tests/service/data/SyntaxTree/Nullness/GenericTypeNotStructAndOtherConstraint-I_am_Still_Sane.fs
new file mode 100644
index 00000000000..8b3b5793b92
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericTypeNotStructAndOtherConstraint-I_am_Still_Sane.fs
@@ -0,0 +1 @@
+type C<'T when 'T: not struct and 'T:equality> = class end
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericTypeNotStructAndOtherConstraint-I_am_Still_Sane.fs.bsl b/tests/service/data/SyntaxTree/Nullness/GenericTypeNotStructAndOtherConstraint-I_am_Still_Sane.fs.bsl
new file mode 100644
index 00000000000..6ebe197154b
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericTypeNotStructAndOtherConstraint-I_am_Still_Sane.fs.bsl
@@ -0,0 +1,34 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/GenericTypeNotStructAndOtherConstraint-I_am_Still_Sane.fs",
+      false,
+      QualifiedNameOfFile GenericTypeNotStructAndOtherConstraint-I_am_Still_Sane,
+      [], [],
+      [SynModuleOrNamespace
+         ([GenericTypeNotStructAndOtherConstraint-I_am_Still_Sane], false,
+          AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([],
+                     Some
+                       (PostfixList
+                          ([SynTyparDecl
+                              ([], SynTypar (T, None, false), [],
+                               { AmpersandRanges = [] })],
+                           [WhereTyparIsReferenceType
+                              (SynTypar (T, None, false), (1,15--1,29));
+                            WhereTyparIsEquatable
+                              (SynTypar (T, None, false), (1,34--1,45))],
+                           (1,6--1,46))), [], [C],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     true, None, (1,5--1,6)),
+                  ObjectModel (Class, [], (1,49--1,58)), [], None, (1,5--1,58),
+                  { LeadingKeyword = Type (1,0--1,4)
+                    EqualsRange = Some (1,47--1,48)
+                    WithKeyword = None })], (1,0--1,58))], PreXmlDocEmpty, [],
+          None, (1,0--2,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(1,0)-(2,0) parse warning The declarations in this file will be placed in an implicit module 'GenericTypeNotStructAndOtherConstraint-I_am_Still_Sane' based on the file name 'GenericTypeNotStructAndOtherConstraint-I_am_Still_Sane.fs'. However this is not a valid F# identifier, so the contents will not be accessible from other files. Consider renaming the file or adding a 'module' or 'namespace' declaration at the top of the file.
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericTypeNull.fs b/tests/service/data/SyntaxTree/Nullness/GenericTypeNull.fs
new file mode 100644
index 00000000000..67b7b23c154
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericTypeNull.fs
@@ -0,0 +1 @@
+type C<'T when 'T: null> = class end
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericTypeNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/GenericTypeNull.fs.bsl
new file mode 100644
index 00000000000..184b29d69d3
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericTypeNull.fs.bsl
@@ -0,0 +1,27 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/GenericTypeNull.fs", false,
+      QualifiedNameOfFile GenericTypeNull, [], [],
+      [SynModuleOrNamespace
+         ([GenericTypeNull], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([],
+                     Some
+                       (PostfixList
+                          ([SynTyparDecl
+                              ([], SynTypar (T, None, false), [],
+                               { AmpersandRanges = [] })],
+                           [WhereTyparSupportsNull
+                              (SynTypar (T, None, false), (1,15--1,23))],
+                           (1,6--1,24))), [], [C],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     true, None, (1,5--1,6)),
+                  ObjectModel (Class, [], (1,27--1,36)), [], None, (1,5--1,36),
+                  { LeadingKeyword = Type (1,0--1,4)
+                    EqualsRange = Some (1,25--1,26)
+                    WithKeyword = None })], (1,0--1,36))], PreXmlDocEmpty, [],
+          None, (1,0--2,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericTypeOtherConstraintAndThenNotNull.fs b/tests/service/data/SyntaxTree/Nullness/GenericTypeOtherConstraintAndThenNotNull.fs
new file mode 100644
index 00000000000..634161d9288
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericTypeOtherConstraintAndThenNotNull.fs
@@ -0,0 +1 @@
+type C<'T when 'T:equality and 'T: not null> = class end
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericTypeOtherConstraintAndThenNotNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/GenericTypeOtherConstraintAndThenNotNull.fs.bsl
new file mode 100644
index 00000000000..14ce1cec8b7
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/GenericTypeOtherConstraintAndThenNotNull.fs.bsl
@@ -0,0 +1,29 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/GenericTypeOtherConstraintAndThenNotNull.fs", false,
+      QualifiedNameOfFile GenericTypeOtherConstraintAndThenNotNull, [], [],
+      [SynModuleOrNamespace
+         ([GenericTypeOtherConstraintAndThenNotNull], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([],
+                     Some
+                       (PostfixList
+                          ([SynTyparDecl
+                              ([], SynTypar (T, None, false), [],
+                               { AmpersandRanges = [] })],
+                           [WhereTyparIsEquatable
+                              (SynTypar (T, None, false), (1,15--1,26));
+                            WhereTyparNotSupportsNull
+                              (SynTypar (T, None, false), (1,31--1,43))],
+                           (1,6--1,44))), [], [C],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     true, None, (1,5--1,6)),
+                  ObjectModel (Class, [], (1,47--1,56)), [], None, (1,5--1,56),
+                  { LeadingKeyword = Type (1,0--1,4)
+                    EqualsRange = Some (1,45--1,46)
+                    WithKeyword = None })], (1,0--1,56))], PreXmlDocEmpty, [],
+          None, (1,0--2,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/IntListOrNull.fs b/tests/service/data/SyntaxTree/Nullness/IntListOrNull.fs
new file mode 100644
index 00000000000..2f3dff3b4c8
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/IntListOrNull.fs
@@ -0,0 +1 @@
+let x : int list | null = []
diff --git a/tests/service/data/SyntaxTree/Nullness/IntListOrNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/IntListOrNull.fs.bsl
new file mode 100644
index 00000000000..3e18b8f3910
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/IntListOrNull.fs.bsl
@@ -0,0 +1,37 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/IntListOrNull.fs", false,
+      QualifiedNameOfFile IntListOrNull, [], [],
+      [SynModuleOrNamespace
+         ([IntListOrNull], false, AnonModule,
+          [Let
+             (false,
+              [SynBinding
+                 (None, Normal, false, false, [],
+                  PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                  SynValData
+                    (None, SynValInfo ([], SynArgInfo ([], false, None)), None,
+                     None), Named (SynIdent (x, None), false, None, (1,4--1,5)),
+                  Some
+                    (SynBindingReturnInfo
+                       (WithNull
+                          (App
+                             (LongIdent (SynLongIdent ([list], [], [None])),
+                              None,
+                              [LongIdent (SynLongIdent ([int], [], [None]))], [],
+                              None, true, (1,8--1,16)), false, (1,8--1,23)),
+                        (1,8--1,23), [], { ColonRange = Some (1,6--1,7) })),
+                  Typed
+                    (ArrayOrList (false, [], (1,26--1,28)),
+                     WithNull
+                       (App
+                          (LongIdent (SynLongIdent ([list], [], [None])), None,
+                           [LongIdent (SynLongIdent ([int], [], [None]))], [],
+                           None, true, (1,8--1,16)), false, (1,8--1,23)),
+                     (1,26--1,28)), (1,4--1,5), Yes (1,0--1,28),
+                  { LeadingKeyword = Let (1,0--1,3)
+                    InlineKeyword = None
+                    EqualsRange = Some (1,24--1,25) })], (1,0--1,28))],
+          PreXmlDocEmpty, [], None, (1,0--2,0), { LeadingKeyword = None })],
+      (true, true), { ConditionalDirectives = []
+                      CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/IntListOrNullOrNullOrNull.fs b/tests/service/data/SyntaxTree/Nullness/IntListOrNullOrNullOrNull.fs
new file mode 100644
index 00000000000..f162f811711
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/IntListOrNullOrNullOrNull.fs
@@ -0,0 +1 @@
+let x : int list | null | null | null = []
diff --git a/tests/service/data/SyntaxTree/Nullness/IntListOrNullOrNullOrNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/IntListOrNullOrNullOrNull.fs.bsl
new file mode 100644
index 00000000000..01b86c58866
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/IntListOrNullOrNullOrNull.fs.bsl
@@ -0,0 +1,39 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/IntListOrNullOrNullOrNull.fs", false,
+      QualifiedNameOfFile IntListOrNullOrNullOrNull, [], [],
+      [SynModuleOrNamespace
+         ([IntListOrNullOrNullOrNull], false, AnonModule,
+          [Let
+             (false,
+              [SynBinding
+                 (None, Normal, false, false, [],
+                  PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                  SynValData
+                    (None, SynValInfo ([], SynArgInfo ([], false, None)), None,
+                     None), Named (SynIdent (x, None), false, None, (1,4--1,5)),
+                  Some
+                    (SynBindingReturnInfo
+                       (WithNull
+                          (App
+                             (LongIdent (SynLongIdent ([list], [], [None])),
+                              None,
+                              [LongIdent (SynLongIdent ([int], [], [None]))], [],
+                              None, true, (1,8--1,16)), false, (1,8--1,23)),
+                        (1,8--1,23), [], { ColonRange = Some (1,6--1,7) })),
+                  Typed
+                    (ArbitraryAfterError ("localBinding2", (1,23--1,23)),
+                     WithNull
+                       (App
+                          (LongIdent (SynLongIdent ([list], [], [None])), None,
+                           [LongIdent (SynLongIdent ([int], [], [None]))], [],
+                           None, true, (1,8--1,16)), false, (1,8--1,23)),
+                     (1,23--1,23)), (1,4--1,5), Yes (1,0--1,23),
+                  { LeadingKeyword = Let (1,0--1,3)
+                    InlineKeyword = None
+                    EqualsRange = None })], (1,0--1,23))], PreXmlDocEmpty, [],
+          None, (1,0--2,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(1,24)-(1,25) parse error Unexpected symbol '|' (directly before 'null') in binding. Expected '=' or other token.
diff --git a/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCast.fs b/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCast.fs
new file mode 100644
index 00000000000..9986cca84a6
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCast.fs
@@ -0,0 +1,2 @@
+match x with
+| :? string | null -> ()
diff --git a/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCast.fs.bsl b/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCast.fs.bsl
new file mode 100644
index 00000000000..86094715714
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCast.fs.bsl
@@ -0,0 +1,23 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/MatchWithTypeCast.fs", false,
+      QualifiedNameOfFile MatchWithTypeCast, [], [],
+      [SynModuleOrNamespace
+         ([MatchWithTypeCast], false, AnonModule,
+          [Expr
+             (Match
+                (Yes (1,0--1,12), Ident x,
+                 [SynMatchClause
+                    (Or
+                       (IsInst
+                          (LongIdent (SynLongIdent ([string], [], [None])),
+                           (2,2--2,11)), Null (2,14--2,18), (2,2--2,18),
+                        { BarRange = (2,12--2,13) }), None,
+                     Const (Unit, (2,22--2,24)), (2,2--2,24), Yes,
+                     { ArrowRange = Some (2,19--2,21)
+                       BarRange = Some (2,0--2,1) })], (1,0--2,24),
+                 { MatchKeyword = (1,0--1,5)
+                   WithKeyword = (1,8--1,12) }), (1,0--2,24))], PreXmlDocEmpty,
+          [], None, (1,0--3,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParens.fs b/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParens.fs
new file mode 100644
index 00000000000..180b3db96df
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParens.fs
@@ -0,0 +1,2 @@
+match x with
+| :? (string | null) -> ()
diff --git a/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParens.fs.bsl b/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParens.fs.bsl
new file mode 100644
index 00000000000..e3a174fcf11
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParens.fs.bsl
@@ -0,0 +1,23 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/MatchWithTypeCastParens.fs", false,
+      QualifiedNameOfFile MatchWithTypeCastParens, [], [],
+      [SynModuleOrNamespace
+         ([MatchWithTypeCastParens], false, AnonModule,
+          [Expr
+             (Match
+                (Yes (1,0--1,12), Ident x,
+                 [SynMatchClause
+                    (IsInst
+                       (Paren
+                          (WithNull
+                             (LongIdent (SynLongIdent ([string], [], [None])),
+                              false, (2,6--2,19)), (2,5--2,20)), (2,2--2,20)),
+                     None, Const (Unit, (2,24--2,26)), (2,2--2,26), Yes,
+                     { ArrowRange = Some (2,21--2,23)
+                       BarRange = Some (2,0--2,1) })], (1,0--2,26),
+                 { MatchKeyword = (1,0--1,5)
+                   WithKeyword = (1,8--1,12) }), (1,0--2,26))], PreXmlDocEmpty,
+          [], None, (1,0--3,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParensAndSeparateNullCase.fs b/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParensAndSeparateNullCase.fs
new file mode 100644
index 00000000000..c738f9f8fed
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParensAndSeparateNullCase.fs
@@ -0,0 +1,2 @@
+match x with
+| :? (string | null) | null -> ()
diff --git a/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParensAndSeparateNullCase.fs.bsl b/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParensAndSeparateNullCase.fs.bsl
new file mode 100644
index 00000000000..2c62cd5cd41
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/MatchWithTypeCastParensAndSeparateNullCase.fs.bsl
@@ -0,0 +1,26 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/MatchWithTypeCastParensAndSeparateNullCase.fs", false,
+      QualifiedNameOfFile MatchWithTypeCastParensAndSeparateNullCase, [], [],
+      [SynModuleOrNamespace
+         ([MatchWithTypeCastParensAndSeparateNullCase], false, AnonModule,
+          [Expr
+             (Match
+                (Yes (1,0--1,12), Ident x,
+                 [SynMatchClause
+                    (Or
+                       (IsInst
+                          (Paren
+                             (WithNull
+                                (LongIdent (SynLongIdent ([string], [], [None])),
+                                 false, (2,6--2,19)), (2,5--2,20)), (2,2--2,20)),
+                        Null (2,23--2,27), (2,2--2,27),
+                        { BarRange = (2,21--2,22) }), None,
+                     Const (Unit, (2,31--2,33)), (2,2--2,33), Yes,
+                     { ArrowRange = Some (2,28--2,30)
+                       BarRange = Some (2,0--2,1) })], (1,0--2,33),
+                 { MatchKeyword = (1,0--1,5)
+                   WithKeyword = (1,8--1,12) }), (1,0--2,33))], PreXmlDocEmpty,
+          [], None, (1,0--3,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs b/tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs
new file mode 100644
index 00000000000..b824f784a61
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs
@@ -0,0 +1 @@
+let x : Expression | null> | null = null
diff --git a/tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs.bsl b/tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs.bsl
new file mode 100644
index 00000000000..c29a384e013
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs.bsl
@@ -0,0 +1,68 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/NullAnnotatedExpression.fs", false,
+      QualifiedNameOfFile NullAnnotatedExpression, [], [],
+      [SynModuleOrNamespace
+         ([NullAnnotatedExpression], false, AnonModule,
+          [Let
+             (false,
+              [SynBinding
+                 (None, Normal, false, false, [],
+                  PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                  SynValData
+                    (None, SynValInfo ([], SynArgInfo ([], false, None)), None,
+                     None), Named (SynIdent (x, None), false, None, (1,4--1,5)),
+                  Some
+                    (SynBindingReturnInfo
+                       (WithNull
+                          (App
+                             (LongIdent
+                                (SynLongIdent ([Expression], [], [None])),
+                              Some (1,18--1,19),
+                              [WithNull
+                                 (App
+                                    (LongIdent
+                                       (SynLongIdent ([Func], [], [None])),
+                                     Some (1,23--1,24),
+                                     [WithNull
+                                        (LongIdent
+                                           (SynLongIdent ([string], [], [None])),
+                                         false, (1,24--1,37));
+                                      WithNull
+                                        (LongIdent
+                                           (SynLongIdent ([T], [], [None])),
+                                         false, (1,39--1,47))], [(1,37--1,38)],
+                                     Some (1,47--1,48), false, (1,19--1,48)),
+                                  false, (1,19--1,55))], [], Some (1,55--1,56),
+                              false, (1,8--1,56)), false, (1,8--1,63)),
+                        (1,8--1,63), [], { ColonRange = Some (1,6--1,7) })),
+                  Typed
+                    (Null (1,66--1,70),
+                     WithNull
+                       (App
+                          (LongIdent (SynLongIdent ([Expression], [], [None])),
+                           Some (1,18--1,19),
+                           [WithNull
+                              (App
+                                 (LongIdent (SynLongIdent ([Func], [], [None])),
+                                  Some (1,23--1,24),
+                                  [WithNull
+                                     (LongIdent
+                                        (SynLongIdent ([string], [], [None])),
+                                      false, (1,24--1,37));
+                                   WithNull
+                                     (LongIdent (SynLongIdent ([T], [], [None])),
+                                      false, (1,39--1,47))], [(1,37--1,38)],
+                                  Some (1,47--1,48), false, (1,19--1,48)), false,
+                               (1,19--1,55))], [], Some (1,55--1,56), false,
+                           (1,8--1,56)), false, (1,8--1,63)), (1,66--1,70)),
+                  (1,4--1,5), Yes (1,0--1,70),
+                  { LeadingKeyword = Let (1,0--1,3)
+                    InlineKeyword = None
+                    EqualsRange = Some (1,64--1,65) })], (1,0--1,70))],
+          PreXmlDocEmpty, [], None, (1,0--2,0), { LeadingKeyword = None })],
+      (true, true), { ConditionalDirectives = []
+                      CodeComments = [] }, set []))
+
+(1,23)-(1,48) parse warning Remove spaces between the type name and type parameter, e.g. "C<'T>", not "C <'T>". Type parameters must be placed directly adjacent to the type name.
+(1,18)-(1,56) parse warning Remove spaces between the type name and type parameter, e.g. "C<'T>", not "C <'T>". Type parameters must be placed directly adjacent to the type name.
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionAnnotatedInlinePatternMatch.fs b/tests/service/data/SyntaxTree/Nullness/RegressionAnnotatedInlinePatternMatch.fs
new file mode 100644
index 00000000000..e608c5198c9
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionAnnotatedInlinePatternMatch.fs
@@ -0,0 +1,2 @@
+match x with 
+| "123" -> "": string | null -> "456"
\ No newline at end of file
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionAnnotatedInlinePatternMatch.fs.bsl b/tests/service/data/SyntaxTree/Nullness/RegressionAnnotatedInlinePatternMatch.fs.bsl
new file mode 100644
index 00000000000..54e114c95ab
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionAnnotatedInlinePatternMatch.fs.bsl
@@ -0,0 +1,29 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/RegressionAnnotatedInlinePatternMatch.fs", false,
+      QualifiedNameOfFile RegressionAnnotatedInlinePatternMatch, [], [],
+      [SynModuleOrNamespace
+         ([RegressionAnnotatedInlinePatternMatch], false, AnonModule,
+          [Expr
+             (Match
+                (Yes (1,0--1,12), Ident x,
+                 [SynMatchClause
+                    (Const (String ("123", Regular, (2,2--2,7)), (2,2--2,7)),
+                     None,
+                     Typed
+                       (Const (String ("", Regular, (2,11--2,13)), (2,11--2,13)),
+                        Fun
+                          (WithNull
+                             (LongIdent (SynLongIdent ([string], [], [None])),
+                              false, (2,15--2,28)),
+                           StaticConstant
+                             (String ("456", Regular, (2,32--2,37)),
+                              (2,32--2,37)), (2,15--2,37),
+                           { ArrowRange = (2,29--2,31) }), (2,11--2,37)),
+                     (2,2--2,37), Yes, { ArrowRange = Some (2,8--2,10)
+                                         BarRange = Some (2,0--2,1) })],
+                 (1,0--2,37), { MatchKeyword = (1,0--1,5)
+                                WithKeyword = (1,8--1,12) }), (1,0--2,37))],
+          PreXmlDocEmpty, [], None, (1,0--2,37), { LeadingKeyword = None })],
+      (true, true), { ConditionalDirectives = []
+                      CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionChoiceType.fs b/tests/service/data/SyntaxTree/Nullness/RegressionChoiceType.fs
new file mode 100644
index 00000000000..dde76747ac4
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionChoiceType.fs
@@ -0,0 +1,7 @@
+type MyChoice<'T1,'T2> = 
+
+  /// Choice 1 of 2 choices
+  | MyChoice of 'T1 
+
+  /// Choice 2 of 2 choices
+  | MyChoice of 'T2
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionChoiceType.fs.bsl b/tests/service/data/SyntaxTree/Nullness/RegressionChoiceType.fs.bsl
new file mode 100644
index 00000000000..3ec9bd46d66
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionChoiceType.fs.bsl
@@ -0,0 +1,53 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/RegressionChoiceType.fs", false,
+      QualifiedNameOfFile RegressionChoiceType, [], [],
+      [SynModuleOrNamespace
+         ([RegressionChoiceType], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([],
+                     Some
+                       (PostfixList
+                          ([SynTyparDecl
+                              ([], SynTypar (T1, None, false), [],
+                               { AmpersandRanges = [] });
+                            SynTyparDecl
+                              ([], SynTypar (T2, None, false), [],
+                               { AmpersandRanges = [] })], [], (1,13--1,22))),
+                     [], [MyChoice],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     true, None, (1,5--1,13)),
+                  Simple
+                    (Union
+                       (None,
+                        [SynUnionCase
+                           ([], SynIdent (MyChoice, None),
+                            Fields
+                              [SynField
+                                 ([], false, None,
+                                  Var (SynTypar (T1, None, false), (4,16--4,19)),
+                                  false,
+                                  PreXmlDoc ((4,16), FSharp.Compiler.Xml.XmlDocCollector),
+                                  None, (4,16--4,19), { LeadingKeyword = None })],
+                            PreXmlDoc ((4,2), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (3,2--4,19), { BarRange = Some (4,2--4,3) });
+                         SynUnionCase
+                           ([], SynIdent (MyChoice, None),
+                            Fields
+                              [SynField
+                                 ([], false, None,
+                                  Var (SynTypar (T2, None, false), (7,16--7,19)),
+                                  false,
+                                  PreXmlDoc ((7,16), FSharp.Compiler.Xml.XmlDocCollector),
+                                  None, (7,16--7,19), { LeadingKeyword = None })],
+                            PreXmlDoc ((7,2), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (6,2--7,19), { BarRange = Some (7,2--7,3) })],
+                        (3,2--7,19)), (3,2--7,19)), [], None, (1,5--7,19),
+                  { LeadingKeyword = Type (1,0--1,4)
+                    EqualsRange = Some (1,23--1,24)
+                    WithKeyword = None })], (1,0--7,19))], PreXmlDocEmpty, [],
+          None, (1,0--8,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionListType.fs b/tests/service/data/SyntaxTree/Nullness/RegressionListType.fs
new file mode 100644
index 00000000000..fca67d8f23e
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionListType.fs
@@ -0,0 +1,3 @@
+type List<'T> = 
+    | ([])  
+    | ( :: )  of Head: 'T * Tail: 'T list
\ No newline at end of file
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionListType.fs.bsl b/tests/service/data/SyntaxTree/Nullness/RegressionListType.fs.bsl
new file mode 100644
index 00000000000..481bbb378bc
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionListType.fs.bsl
@@ -0,0 +1,63 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/RegressionListType.fs", false,
+      QualifiedNameOfFile RegressionListType, [], [],
+      [SynModuleOrNamespace
+         ([RegressionListType], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([],
+                     Some
+                       (PostfixList
+                          ([SynTyparDecl
+                              ([], SynTypar (T, None, false), [],
+                               { AmpersandRanges = [] })], [], (1,9--1,13))), [],
+                     [List],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     true, None, (1,5--1,9)),
+                  Simple
+                    (Union
+                       (None,
+                        [SynUnionCase
+                           ([],
+                            SynIdent
+                              (op_Nil,
+                               Some
+                                 (OriginalNotationWithParen
+                                    ((2,6--2,7), "[]", (2,8--2,9)))), Fields [],
+                            PreXmlDoc ((2,4), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (2,6--2,10), { BarRange = Some (2,4--2,5) });
+                         SynUnionCase
+                           ([],
+                            SynIdent
+                              (op_ColonColon,
+                               Some
+                                 (OriginalNotationWithParen
+                                    ((3,6--3,7), "::", (3,11--3,12)))),
+                            Fields
+                              [SynField
+                                 ([], false, Some Head,
+                                  Var (SynTypar (T, None, false), (3,23--3,25)),
+                                  false,
+                                  PreXmlDoc ((3,17), FSharp.Compiler.Xml.XmlDocCollector),
+                                  None, (3,17--3,25), { LeadingKeyword = None });
+                               SynField
+                                 ([], false, Some Tail,
+                                  App
+                                    (LongIdent
+                                       (SynLongIdent ([list], [], [None])), None,
+                                     [Var
+                                        (SynTypar (T, None, false), (3,34--3,36))],
+                                     [], None, true, (3,34--3,41)), false,
+                                  PreXmlDoc ((3,28), FSharp.Compiler.Xml.XmlDocCollector),
+                                  None, (3,28--3,41), { LeadingKeyword = None })],
+                            PreXmlDoc ((3,4), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (3,6--3,41), { BarRange = Some (3,4--3,5) })],
+                        (2,4--3,41)), (2,4--3,41)), [], None, (1,5--3,41),
+                  { LeadingKeyword = Type (1,0--1,4)
+                    EqualsRange = Some (1,14--1,15)
+                    WithKeyword = None })], (1,0--3,41))], PreXmlDocEmpty, [],
+          None, (1,0--3,41), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionOneLinerOptionType.fs b/tests/service/data/SyntaxTree/Nullness/RegressionOneLinerOptionType.fs
new file mode 100644
index 00000000000..4b54405dff0
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionOneLinerOptionType.fs
@@ -0,0 +1 @@
+type MyFlatOption = None | Some of string
\ No newline at end of file
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionOneLinerOptionType.fs.bsl b/tests/service/data/SyntaxTree/Nullness/RegressionOneLinerOptionType.fs.bsl
new file mode 100644
index 00000000000..5b785c961d5
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionOneLinerOptionType.fs.bsl
@@ -0,0 +1,37 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/RegressionOneLinerOptionType.fs", false,
+      QualifiedNameOfFile RegressionOneLinerOptionType, [], [],
+      [SynModuleOrNamespace
+         ([RegressionOneLinerOptionType], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [MyFlatOption],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (1,5--1,17)),
+                  Simple
+                    (Union
+                       (None,
+                        [SynUnionCase
+                           ([], SynIdent (None, None), Fields [],
+                            PreXmlDoc ((1,20), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (1,20--1,24), { BarRange = None });
+                         SynUnionCase
+                           ([], SynIdent (Some, None),
+                            Fields
+                              [SynField
+                                 ([], false, None,
+                                  LongIdent
+                                    (SynLongIdent ([string], [], [None])), false,
+                                  PreXmlDoc ((1,35), FSharp.Compiler.Xml.XmlDocCollector),
+                                  None, (1,35--1,41), { LeadingKeyword = None })],
+                            PreXmlDoc ((1,25), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (1,27--1,41), { BarRange = Some (1,25--1,26) })],
+                        (1,20--1,41)), (1,20--1,41)), [], None, (1,5--1,41),
+                  { LeadingKeyword = Type (1,0--1,4)
+                    EqualsRange = Some (1,18--1,19)
+                    WithKeyword = None })], (1,0--1,41))], PreXmlDocEmpty, [],
+          None, (1,0--1,41), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionOptionType.fs b/tests/service/data/SyntaxTree/Nullness/RegressionOptionType.fs
new file mode 100644
index 00000000000..8b1018d513f
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionOptionType.fs
@@ -0,0 +1,3 @@
+type Option<'T> =
+    | None:       'T option
+    | Some: Value:'T -> 'T option 
\ No newline at end of file
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionOptionType.fs.bsl b/tests/service/data/SyntaxTree/Nullness/RegressionOptionType.fs.bsl
new file mode 100644
index 00000000000..5491684ccaa
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionOptionType.fs.bsl
@@ -0,0 +1,64 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/RegressionOptionType.fs", false,
+      QualifiedNameOfFile RegressionOptionType, [], [],
+      [SynModuleOrNamespace
+         ([RegressionOptionType], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([],
+                     Some
+                       (PostfixList
+                          ([SynTyparDecl
+                              ([], SynTypar (T, None, false), [],
+                               { AmpersandRanges = [] })], [], (1,11--1,15))),
+                     [], [Option],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     true, None, (1,5--1,11)),
+                  Simple
+                    (Union
+                       (None,
+                        [SynUnionCase
+                           ([], SynIdent (None, None),
+                            FullType
+                              (App
+                                 (LongIdent
+                                    (SynLongIdent ([option], [], [None])), None,
+                                  [Var (SynTypar (T, None, false), (2,18--2,20))],
+                                  [], None, true, (2,18--2,27)),
+                               SynValInfo ([], SynArgInfo ([], false, None))),
+                            PreXmlDoc ((2,4), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (2,6--2,27), { BarRange = Some (2,4--2,5) });
+                         SynUnionCase
+                           ([], SynIdent (Some, None),
+                            FullType
+                              (Fun
+                                 (SignatureParameter
+                                    ([], false, Some Value,
+                                     Var
+                                       (SynTypar (T, None, false), (3,18--3,20)),
+                                     (3,12--3,20)),
+                                  App
+                                    (LongIdent
+                                       (SynLongIdent ([option], [], [None])),
+                                     None,
+                                     [Var
+                                        (SynTypar (T, None, false), (3,24--3,26))],
+                                     [], None, true, (3,24--3,33)), (3,12--3,33),
+                                  { ArrowRange = (3,21--3,23) }),
+                               SynValInfo
+                                 ([[SynArgInfo ([], false, Some Value)]],
+                                  SynArgInfo ([], false, None))),
+                            PreXmlDoc ((3,4), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (3,6--3,33), { BarRange = Some (3,4--3,5) })],
+                        (2,4--3,33)), (2,4--3,33)), [], None, (1,5--3,33),
+                  { LeadingKeyword = Type (1,0--1,4)
+                    EqualsRange = Some (1,16--1,17)
+                    WithKeyword = None })], (1,0--3,33))], PreXmlDocEmpty, [],
+          None, (1,0--3,34), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(2,6)-(2,27) parse warning This construct is deprecated: it is only for use in the F# library
+(3,6)-(3,33) parse warning This construct is deprecated: it is only for use in the F# library
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionOrPattern.fs b/tests/service/data/SyntaxTree/Nullness/RegressionOrPattern.fs
new file mode 100644
index 00000000000..d8374a93f90
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionOrPattern.fs
@@ -0,0 +1,3 @@
+match exn with
+| InternalError (s, _)
+| Failure s as exn -> ()
\ No newline at end of file
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionOrPattern.fs.bsl b/tests/service/data/SyntaxTree/Nullness/RegressionOrPattern.fs.bsl
new file mode 100644
index 00000000000..82fe5cb33d5
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionOrPattern.fs.bsl
@@ -0,0 +1,40 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/RegressionOrPattern.fs", false,
+      QualifiedNameOfFile RegressionOrPattern, [], [],
+      [SynModuleOrNamespace
+         ([RegressionOrPattern], false, AnonModule,
+          [Expr
+             (Match
+                (Yes (1,0--1,14), Ident exn,
+                 [SynMatchClause
+                    (As
+                       (Or
+                          (LongIdent
+                             (SynLongIdent ([InternalError], [], [None]), None,
+                              None,
+                              Pats
+                                [Paren
+                                   (Tuple
+                                      (false,
+                                       [Named
+                                          (SynIdent (s, None), false, None,
+                                           (2,17--2,18)); Wild (2,20--2,21)],
+                                       [(2,18--2,19)], (2,17--2,21)),
+                                    (2,16--2,22))], None, (2,2--2,22)),
+                           LongIdent
+                             (SynLongIdent ([Failure], [], [None]), None, None,
+                              Pats
+                                [Named
+                                   (SynIdent (s, None), false, None,
+                                    (3,10--3,11))], None, (3,2--3,11)),
+                           (2,2--3,11), { BarRange = (3,0--3,1) }),
+                        Named (SynIdent (exn, None), false, None, (3,15--3,18)),
+                        (2,2--3,18)), None, Const (Unit, (3,22--3,24)),
+                     (2,2--3,24), Yes, { ArrowRange = Some (3,19--3,21)
+                                         BarRange = Some (2,0--2,1) })],
+                 (1,0--3,24), { MatchKeyword = (1,0--1,5)
+                                WithKeyword = (1,10--1,14) }), (1,0--3,24))],
+          PreXmlDocEmpty, [], None, (1,0--3,24), { LeadingKeyword = None })],
+      (true, true), { ConditionalDirectives = []
+                      CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionResultType.fs b/tests/service/data/SyntaxTree/Nullness/RegressionResultType.fs
new file mode 100644
index 00000000000..b2974154002
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionResultType.fs
@@ -0,0 +1,7 @@
+    type MyResult<'T,'TError> = 
+
+      /// Represents an OK or a Successful result. The code succeeded with a value of 'T.
+      | Ok of ResultValue:'T 
+
+      /// Represents an Error or a Failure. The code failed with a value of 'TError representing what went wrong.
+      | Error of ErrorValue:'TError
\ No newline at end of file
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionResultType.fs.bsl b/tests/service/data/SyntaxTree/Nullness/RegressionResultType.fs.bsl
new file mode 100644
index 00000000000..fea7c9a9a59
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionResultType.fs.bsl
@@ -0,0 +1,54 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/RegressionResultType.fs", false,
+      QualifiedNameOfFile RegressionResultType, [], [],
+      [SynModuleOrNamespace
+         ([RegressionResultType], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([],
+                     Some
+                       (PostfixList
+                          ([SynTyparDecl
+                              ([], SynTypar (T, None, false), [],
+                               { AmpersandRanges = [] });
+                            SynTyparDecl
+                              ([], SynTypar (TError, None, false), [],
+                               { AmpersandRanges = [] })], [], (1,17--1,29))),
+                     [], [MyResult],
+                     PreXmlDoc ((1,4), FSharp.Compiler.Xml.XmlDocCollector),
+                     true, None, (1,9--1,17)),
+                  Simple
+                    (Union
+                       (None,
+                        [SynUnionCase
+                           ([], SynIdent (Ok, None),
+                            Fields
+                              [SynField
+                                 ([], false, Some ResultValue,
+                                  Var (SynTypar (T, None, false), (4,26--4,28)),
+                                  false,
+                                  PreXmlDoc ((4,14), FSharp.Compiler.Xml.XmlDocCollector),
+                                  None, (4,14--4,28), { LeadingKeyword = None })],
+                            PreXmlDoc ((4,6), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (3,6--4,28), { BarRange = Some (4,6--4,7) });
+                         SynUnionCase
+                           ([], SynIdent (Error, None),
+                            Fields
+                              [SynField
+                                 ([], false, Some ErrorValue,
+                                  Var
+                                    (SynTypar (TError, None, false),
+                                     (7,28--7,35)), false,
+                                  PreXmlDoc ((7,17), FSharp.Compiler.Xml.XmlDocCollector),
+                                  None, (7,17--7,35), { LeadingKeyword = None })],
+                            PreXmlDoc ((7,6), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (6,6--7,35), { BarRange = Some (7,6--7,7) })],
+                        (3,6--7,35)), (3,6--7,35)), [], None, (1,9--7,35),
+                  { LeadingKeyword = Type (1,4--1,8)
+                    EqualsRange = Some (1,30--1,31)
+                    WithKeyword = None })], (1,4--7,35))], PreXmlDocEmpty, [],
+          None, (1,4--7,35), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/SignatureInAbstractMember.fs b/tests/service/data/SyntaxTree/Nullness/SignatureInAbstractMember.fs
new file mode 100644
index 00000000000..9839c9cd370
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/SignatureInAbstractMember.fs
@@ -0,0 +1,2 @@
+type MyClassBase1() =
+   abstract member function1 : string | null -> string | null
diff --git a/tests/service/data/SyntaxTree/Nullness/SignatureInAbstractMember.fs.bsl b/tests/service/data/SyntaxTree/Nullness/SignatureInAbstractMember.fs.bsl
new file mode 100644
index 00000000000..b7cfdabef4f
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/SignatureInAbstractMember.fs.bsl
@@ -0,0 +1,60 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/SignatureInAbstractMember.fs", false,
+      QualifiedNameOfFile SignatureInAbstractMember, [], [],
+      [SynModuleOrNamespace
+         ([SignatureInAbstractMember], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [MyClassBase1],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (1,5--1,17)),
+                  ObjectModel
+                    (Unspecified,
+                     [ImplicitCtor
+                        (None, [], SimplePats ([], [], (1,17--1,19)), None,
+                         PreXmlDoc ((1,17), FSharp.Compiler.Xml.XmlDocCollector),
+                         (1,5--1,17), { AsKeyword = None });
+                      AbstractSlot
+                        (SynValSig
+                           ([], SynIdent (function1, None),
+                            SynValTyparDecls (None, true),
+                            Fun
+                              (WithNull
+                                 (LongIdent
+                                    (SynLongIdent ([string], [], [None])), false,
+                                  (2,31--2,44)),
+                               WithNull
+                                 (LongIdent
+                                    (SynLongIdent ([string], [], [None])), false,
+                                  (2,48--2,61)), (2,31--2,61),
+                               { ArrowRange = (2,45--2,47) }),
+                            SynValInfo
+                              ([[SynArgInfo ([], false, None)]],
+                               SynArgInfo ([], false, None)), false, false,
+                            PreXmlDoc ((2,3), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, None, (2,3--2,61),
+                            { LeadingKeyword =
+                               AbstractMember ((2,3--2,11), (2,12--2,18))
+                              InlineKeyword = None
+                              WithKeyword = None
+                              EqualsRange = None }),
+                         { IsInstance = true
+                           IsDispatchSlot = true
+                           IsOverrideOrExplicitImpl = false
+                           IsFinal = false
+                           GetterOrSetterIsCompilerGenerated = false
+                           MemberKind = Member }, (2,3--2,61),
+                         { GetSetKeywords = None })], (2,3--2,61)), [],
+                  Some
+                    (ImplicitCtor
+                       (None, [], SimplePats ([], [], (1,17--1,19)), None,
+                        PreXmlDoc ((1,17), FSharp.Compiler.Xml.XmlDocCollector),
+                        (1,5--1,17), { AsKeyword = None })), (1,5--2,61),
+                  { LeadingKeyword = Type (1,0--1,4)
+                    EqualsRange = Some (1,20--1,21)
+                    WithKeyword = None })], (1,0--2,61))], PreXmlDocEmpty, [],
+          None, (1,0--3,0), { LeadingKeyword = None })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/StringOrNull.fs b/tests/service/data/SyntaxTree/Nullness/StringOrNull.fs
new file mode 100644
index 00000000000..f27f3c86f09
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/StringOrNull.fs
@@ -0,0 +1 @@
+let x : string | null = null
diff --git a/tests/service/data/SyntaxTree/Nullness/StringOrNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/StringOrNull.fs.bsl
new file mode 100644
index 00000000000..f73e3f6ab3a
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/StringOrNull.fs.bsl
@@ -0,0 +1,31 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/StringOrNull.fs", false, QualifiedNameOfFile StringOrNull,
+      [], [],
+      [SynModuleOrNamespace
+         ([StringOrNull], false, AnonModule,
+          [Let
+             (false,
+              [SynBinding
+                 (None, Normal, false, false, [],
+                  PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                  SynValData
+                    (None, SynValInfo ([], SynArgInfo ([], false, None)), None,
+                     None), Named (SynIdent (x, None), false, None, (1,4--1,5)),
+                  Some
+                    (SynBindingReturnInfo
+                       (WithNull
+                          (LongIdent (SynLongIdent ([string], [], [None])),
+                           false, (1,8--1,21)), (1,8--1,21), [],
+                        { ColonRange = Some (1,6--1,7) })),
+                  Typed
+                    (Null (1,24--1,28),
+                     WithNull
+                       (LongIdent (SynLongIdent ([string], [], [None])), false,
+                        (1,8--1,21)), (1,24--1,28)), (1,4--1,5), Yes (1,0--1,28),
+                  { LeadingKeyword = Let (1,0--1,3)
+                    InlineKeyword = None
+                    EqualsRange = Some (1,22--1,23) })], (1,0--1,28))],
+          PreXmlDocEmpty, [], None, (1,0--2,0), { LeadingKeyword = None })],
+      (true, true), { ConditionalDirectives = []
+                      CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/StringOrNullInFunctionArg.fs b/tests/service/data/SyntaxTree/Nullness/StringOrNullInFunctionArg.fs
new file mode 100644
index 00000000000..37569d4900a
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/StringOrNullInFunctionArg.fs
@@ -0,0 +1 @@
+let myFunc (x: (string | null)) = 42
diff --git a/tests/service/data/SyntaxTree/Nullness/StringOrNullInFunctionArg.fs.bsl b/tests/service/data/SyntaxTree/Nullness/StringOrNullInFunctionArg.fs.bsl
new file mode 100644
index 00000000000..c10d17ee85f
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/StringOrNullInFunctionArg.fs.bsl
@@ -0,0 +1,36 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/StringOrNullInFunctionArg.fs", false,
+      QualifiedNameOfFile StringOrNullInFunctionArg, [], [],
+      [SynModuleOrNamespace
+         ([StringOrNullInFunctionArg], false, AnonModule,
+          [Let
+             (false,
+              [SynBinding
+                 (None, Normal, false, false, [],
+                  PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                  SynValData
+                    (None,
+                     SynValInfo
+                       ([[SynArgInfo ([], false, Some x)]],
+                        SynArgInfo ([], false, None)), None, None),
+                  LongIdent
+                    (SynLongIdent ([myFunc], [], [None]), None, None,
+                     Pats
+                       [Paren
+                          (Typed
+                             (Named
+                                (SynIdent (x, None), false, None, (1,12--1,13)),
+                              Paren
+                                (WithNull
+                                   (LongIdent
+                                      (SynLongIdent ([string], [], [None])),
+                                    false, (1,16--1,29)), (1,15--1,30)),
+                              (1,12--1,30)), (1,11--1,31))], None, (1,4--1,31)),
+                  None, Const (Int32 42, (1,34--1,36)), (1,4--1,31), NoneAtLet,
+                  { LeadingKeyword = Let (1,0--1,3)
+                    InlineKeyword = None
+                    EqualsRange = Some (1,32--1,33) })], (1,0--1,36))],
+          PreXmlDocEmpty, [], None, (1,0--2,0), { LeadingKeyword = None })],
+      (true, true), { ConditionalDirectives = []
+                      CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Nullness/TypeAbbreviationAddingWithNull.fs b/tests/service/data/SyntaxTree/Nullness/TypeAbbreviationAddingWithNull.fs
new file mode 100644
index 00000000000..194814afffa
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/TypeAbbreviationAddingWithNull.fs
@@ -0,0 +1 @@
+type MyFlatOption = string | null
\ No newline at end of file
diff --git a/tests/service/data/SyntaxTree/Nullness/TypeAbbreviationAddingWithNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/TypeAbbreviationAddingWithNull.fs.bsl
new file mode 100644
index 00000000000..1a874cb67b7
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Nullness/TypeAbbreviationAddingWithNull.fs.bsl
@@ -0,0 +1,24 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Nullness/TypeAbbreviationAddingWithNull.fs", false,
+      QualifiedNameOfFile TypeAbbreviationAddingWithNull, [], [],
+      [SynModuleOrNamespace
+         ([TypeAbbreviationAddingWithNull], false, AnonModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [MyFlatOption],
+                     PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (1,5--1,17)),
+                  Simple
+                    (TypeAbbrev
+                       (Ok,
+                        WithNull
+                          (LongIdent (SynLongIdent ([string], [], [None])),
+                           false, (1,20--1,33)), (1,20--1,33)), (1,20--1,33)),
+                  [], None, (1,5--1,33), { LeadingKeyword = Type (1,0--1,4)
+                                           EqualsRange = Some (1,18--1,19)
+                                           WithKeyword = None })], (1,0--1,33))],
+          PreXmlDocEmpty, [], None, (1,0--1,33), { LeadingKeyword = None })],
+      (true, true), { ConditionalDirectives = []
+                      CodeComments = [] }, set []))

From 0d45bb97674379b8f99fa49a31fa2590042730a7 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Fri, 8 Sep 2023 15:00:37 +0200
Subject: [PATCH 25/59] applying changed syntax

---
 src/Compiler/Checking/CheckExpressions.fs    |  2 +-
 src/Compiler/Checking/ConstraintSolver.fs    |  4 +-
 src/Compiler/Checking/NicePrint.fs           |  4 +-
 src/Compiler/Driver/CompilerDiagnostics.fs   |  4 +-
 src/Compiler/FSStrings.resx                  |  6 --
 src/Compiler/Service/ServiceLexing.fs        |  3 -
 src/Compiler/SyntaxTree/LexFilter.fs         |  7 +-
 src/Compiler/SyntaxTree/LexHelpers.fs        |  4 --
 src/Compiler/TypedTree/TypeProviders.fs      | 10 +--
 src/Compiler/TypedTree/tainted.fs            |  2 +-
 src/Compiler/TypedTree/tainted.fsi           |  2 +-
 src/Compiler/Utilities/illib.fs              |  2 +-
 src/Compiler/Utilities/illib.fsi             |  2 +-
 src/Compiler/pars.fsy                        | 33 +--------
 src/Compiler/xlf/FSStrings.cs.xlf            | 10 ---
 src/Compiler/xlf/FSStrings.de.xlf            | 10 ---
 src/Compiler/xlf/FSStrings.es.xlf            | 10 ---
 src/Compiler/xlf/FSStrings.fr.xlf            | 10 ---
 src/Compiler/xlf/FSStrings.it.xlf            | 10 ---
 src/Compiler/xlf/FSStrings.ja.xlf            | 10 ---
 src/Compiler/xlf/FSStrings.ko.xlf            | 10 ---
 src/Compiler/xlf/FSStrings.pl.xlf            | 10 ---
 src/Compiler/xlf/FSStrings.pt-BR.xlf         | 10 ---
 src/Compiler/xlf/FSStrings.ru.xlf            | 10 ---
 src/Compiler/xlf/FSStrings.tr.xlf            | 10 ---
 src/Compiler/xlf/FSStrings.zh-Hans.xlf       | 10 ---
 src/Compiler/xlf/FSStrings.zh-Hant.xlf       | 10 ---
 src/FSharp.Build/FSharpCommandLineBuilder.fs |  2 +-
 src/FSharp.Core/array.fs                     |  4 +-
 src/FSharp.Core/async.fs                     |  2 +-
 src/FSharp.Core/local.fs                     |  2 +-
 src/FSharp.Core/option.fs                    |  8 +--
 src/FSharp.Core/option.fsi                   |  8 +--
 src/FSharp.Core/prim-types.fs                | 12 ++--
 src/FSharp.Core/prim-types.fsi               | 14 ++--
 src/fsi/console.fs                           |  2 +-
 tests/adhoc/nullness/enabled/negative.fs     |  4 +-
 tests/adhoc/nullness/enabled/positive.fs     | 74 ++++++++++----------
 38 files changed, 84 insertions(+), 263 deletions(-)

diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs
index 08f3104203b..ba49b8356b2 100644
--- a/src/Compiler/Checking/CheckExpressions.fs
+++ b/src/Compiler/Checking/CheckExpressions.fs
@@ -996,7 +996,7 @@ let TcAddNullnessToType (warn: bool) (cenv: cenv) (env: TcEnv) nullness innerTyC
             // For example "int option?" is not allowed, nor "string??".
             //
             // For variable types in FSharp.Core we make an exception because we must allow
-            //    val toObj: value: 'T option -> 'T __withnull when 'T : not struct (* and 'T : __notnull *)
+            //    val toObj: value: 'T option -> 'T | null when 'T : not struct (* and 'T : not null *)
             // wihout implying 'T is not null.  This is because it is legitimate to use this
             // function to "collapse" null and obj-null-coming-from-option using such a function.
 
diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs
index d624abf78c5..6be1aedfa60 100644
--- a/src/Compiler/Checking/ConstraintSolver.fs
+++ b/src/Compiler/Checking/ConstraintSolver.fs
@@ -2513,7 +2513,7 @@ and AddConstraint (csenv: ConstraintSolverEnv) ndeep m2 trace tp newConstraint
 //
 //    val checkNonNull1: argName: string -> arg: 'T -> unit when 'T: null
 //
-//    val checkNonNull2: argName: string -> arg: 'T __withnull -> unit
+//    val checkNonNull2: argName: string -> arg: 'T | null -> unit
 //
 // When null checking is fully enabled, we prefer the latter. We can't always prefer it because it is a breaking change.
 //
@@ -2523,7 +2523,7 @@ and AddConstraint (csenv: ConstraintSolverEnv) ndeep m2 trace tp newConstraint
 //
 // What's the generalized type?
 //    val x: 'a when 'a: null
-//    val x: 'a __withnull when 'a: not null
+//    val x: 'a | null when 'a: not null
 //
 // When null checking is fully enabled, we prefer the latter. We can't always prefer it because it is a breaking change.
 and SolveTypeUseSupportsNull (csenv: ConstraintSolverEnv) ndeep m2 trace ty = 
diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs
index 3e35cd4f32c..c946d09f0c8 100644
--- a/src/Compiler/Checking/NicePrint.fs
+++ b/src/Compiler/Checking/NicePrint.fs
@@ -798,7 +798,7 @@ module PrintTypes =
             [wordL (tagKeyword "null") |> longConstraintPrefix]
 
         | TyparConstraint.NotSupportsNull _ ->
-                [(wordL (tagKeyword "__notnull") (* ^^ wordL(tagKeyword "null") *) ) |> longConstraintPrefix]
+                [(wordL (tagKeyword "not null") (* ^^ wordL(tagKeyword "null") *) ) |> longConstraintPrefix]
 
         | TyparConstraint.IsNonNullableStruct _ ->
             if denv.shortConstraints then 
@@ -910,7 +910,7 @@ module PrintTypes =
         // Show nullness annotations unless explicitly turned off
         if denv.showNullnessAnnotations <> Some false then
             match nullness.Evaluate() with
-            | NullnessInfo.WithNull -> part2 ^^ wordL (tagText "__withnull")
+            | NullnessInfo.WithNull -> part2 ^^ wordL (tagText "| null")
             | NullnessInfo.WithoutNull -> part2
             | NullnessInfo.AmbivalentToNull -> part2 //^^ wordL (tagText "__maybenull")
         else
diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs
index 34e202d5018..89ea86c44b2 100644
--- a/src/Compiler/Driver/CompilerDiagnostics.fs
+++ b/src/Compiler/Driver/CompilerDiagnostics.fs
@@ -1286,9 +1286,7 @@ type Exception with
                 | Parser.TOKEN_INTERP_STRING_BEGIN_END -> SR.GetString("Parser.TOKEN.INTERP.STRING.BEGIN.END")
                 | Parser.TOKEN_INTERP_STRING_BEGIN_PART -> SR.GetString("Parser.TOKEN.INTERP.STRING.BEGIN.PART")
                 | Parser.TOKEN_INTERP_STRING_PART -> SR.GetString("Parser.TOKEN.INTERP.STRING.PART")
-                | Parser.TOKEN_INTERP_STRING_END -> SR.GetString("Parser.TOKEN.INTERP.STRING.END")
-                | Parser.TOKEN_WITHNULL__ -> SR.GetString("Parser.TOKEN.WITHNULL__")
-                | Parser.TOKEN_NOTNULL__ -> SR.GetString("Parser.TOKEN.NOTNULL__")
+                | Parser.TOKEN_INTERP_STRING_END -> SR.GetString("Parser.TOKEN.INTERP.STRING.END")              
                 | Parser.TOKEN_BAR_JUST_BEFORE_NULL -> SR.GetString("Parser.TOKEN.BAR_JUST_BEFORE_NULL")
                 | unknown ->
                     let result = sprintf "unknown token tag %+A" unknown
diff --git a/src/Compiler/FSStrings.resx b/src/Compiler/FSStrings.resx
index 3af0391078c..93d2e643350 100644
--- a/src/Compiler/FSStrings.resx
+++ b/src/Compiler/FSStrings.resx
@@ -456,12 +456,6 @@
   
     keyword 'fixed'
   
-  
-    keyword '__withnull'
-  
-  
-    keyword '__notnull'
-  
   
     interpolated string
   
diff --git a/src/Compiler/Service/ServiceLexing.fs b/src/Compiler/Service/ServiceLexing.fs
index c8f4797021c..d8eb10a7662 100644
--- a/src/Compiler/Service/ServiceLexing.fs
+++ b/src/Compiler/Service/ServiceLexing.fs
@@ -392,9 +392,6 @@ module internal TokenClassifications =
         | HIGH_PRECEDENCE_PAREN_APP
         | FIXED
         | HIGH_PRECEDENCE_BRACK_APP
-        | MAYBENULL__
-        | NOTNULL__
-        | WITHNULL__
         | BAR_JUST_BEFORE_NULL
         | TYPE_COMING_SOON
         | TYPE_IS_HERE
diff --git a/src/Compiler/SyntaxTree/LexFilter.fs b/src/Compiler/SyntaxTree/LexFilter.fs
index d17c27d7329..a4f68b98841 100644
--- a/src/Compiler/SyntaxTree/LexFilter.fs
+++ b/src/Compiler/SyntaxTree/LexFilter.fs
@@ -1122,12 +1122,9 @@ type LexFilterImpl (
                     //      f<{| C : int |}>x
                     //      fx
                     //      fx
-                    //      fx
-                    //      fx
-                    //      fx
-                    //      fx
+                    //      fx
                     | DEFAULT | COLON | COLON_GREATER | STRUCT | NULL | DELEGATE | AND | WHEN | AMP
-                    | NOTNULL__ | MAYBENULL__ | WITHNULL__ | BAR_JUST_BEFORE_NULL
+                    | BAR_JUST_BEFORE_NULL
                     | DOT_DOT
                     | NEW
                     | LBRACE_BAR
diff --git a/src/Compiler/SyntaxTree/LexHelpers.fs b/src/Compiler/SyntaxTree/LexHelpers.fs
index b5e4faf4c38..02d4da364d4 100644
--- a/src/Compiler/SyntaxTree/LexHelpers.fs
+++ b/src/Compiler/SyntaxTree/LexHelpers.fs
@@ -399,10 +399,6 @@ module Keywords =
             FSHARP, "__token_ODO", ODO
             FSHARP, "__token_OLET", OLET(true)
             FSHARP, "__token_constraint", CONSTRAINT
-            (*------- for prototyping *)
-            FSHARP, "__maybenull", MAYBENULL__
-            FSHARP, "__notnull", NOTNULL__
-            FSHARP, "__withnull", WITHNULL__
         ]
         (*------- reserved keywords which are ml-compatibility ids *)
         @ List.map
diff --git a/src/Compiler/TypedTree/TypeProviders.fs b/src/Compiler/TypedTree/TypeProviders.fs
index 34eefe3d3e4..7953a374de5 100644
--- a/src/Compiler/TypedTree/TypeProviders.fs
+++ b/src/Compiler/TypedTree/TypeProviders.fs
@@ -231,8 +231,8 @@ let TryTypeMemberArray (st: Tainted<_>, fullName, memberName, m, f) =
 let TryTypeMemberNonNull<'T, 'U when 'U : null and 'U : not struct>(st: Tainted<'T>, fullName, memberName, m, recover: 'U, (f: 'T -> 'U)) : Tainted<'U> =
     match TryTypeMember(st, fullName, memberName, m, recover, f) with 
 #else
-let TryTypeMemberNonNull<'T, 'U when 'U : __notnull and 'U : not struct>(st: Tainted<'T>, fullName, memberName, m, recover: 'U, (f: 'T -> 'U __withnull)) : Tainted<'U> =
-    match TryTypeMember<'T, 'U __withnull>(st, fullName, memberName, m, withNull recover, f) with 
+let TryTypeMemberNonNull<'T, 'U when 'U : not null and 'U : not struct>(st: Tainted<'T>, fullName, memberName, m, recover: 'U, (f: 'T -> 'U | null)) : Tainted<'U> =
+    match TryTypeMember<'T, 'U | null>(st, fullName, memberName, m, withNull recover, f) with 
 #endif
     | Tainted.Null -> 
         errorR(Error(FSComp.SR.etUnexpectedNullFromProvidedTypeMember(fullName, memberName), m))
@@ -1122,7 +1122,7 @@ let ValidateExpectedName m expectedPath expectedName (st: Tainted)
 #if NO_CHECKNULLS
     let namespaceName = TryTypeMember(st, name, "Namespace", m, "", fun st -> st.Namespace) |> unmarshal
 #else
-    let namespaceName = TryTypeMember<_, string __withnull>(st, name, "Namespace", m, "", fun st -> st.Namespace) |> unmarshal // TODO NULLNESS: why is this explicit instantiation needed?
+    let namespaceName = TryTypeMember<_, string | null>(st, name, "Namespace", m, "", fun st -> st.Namespace) |> unmarshal // TODO NULLNESS: why is this explicit instantiation needed?
 #endif
 
     let rec declaringTypes (st: Tainted) accu =
@@ -1149,7 +1149,7 @@ let ValidateProvidedTypeAfterStaticInstantiation(m, st: Tainted, e
 #if NO_CHECKNULLS
         let namespaceName = TryTypeMember(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal
 #else
-        let namespaceName = TryTypeMember<_, string __withnull>(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal
+        let namespaceName = TryTypeMember<_, string | null>(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal
 #endif
         let fullName = TryTypeMemberNonNull(st, name, "FullName", m, FSComp.SR.invalidFullNameForProvidedType(), fun st -> st.FullName) |> unmarshal
         ValidateExpectedName m expectedPath expectedName st
@@ -1258,7 +1258,7 @@ let ValidateProvidedTypeDefinition(m, st: Tainted, expectedPath: s
 #if NO_CHECKNULLS
     let _namespaceName = TryTypeMember(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal
 #else
-    let _namespaceName = TryTypeMember<_, string __withnull>(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal
+    let _namespaceName = TryTypeMember<_, string | null>(st, name, "Namespace", m, FSComp.SR.invalidNamespaceForProvidedType(), fun st -> st.Namespace) |> unmarshal
 #endif
     let _fullname = TryTypeMemberNonNull(st, name, "FullName", m, FSComp.SR.invalidFullNameForProvidedType(), fun st -> st.FullName)  |> unmarshal
     ValidateExpectedName m expectedPath expectedName st
diff --git a/src/Compiler/TypedTree/tainted.fs b/src/Compiler/TypedTree/tainted.fs
index 0c825c3a11b..dcbd640e2a6 100644
--- a/src/Compiler/TypedTree/tainted.fs
+++ b/src/Compiler/TypedTree/tainted.fs
@@ -168,7 +168,7 @@ module internal Tainted =
     let (|Null|NonNull|) (p:Tainted<'T>) : Choice> when 'T : null and 'T : not struct =
         if p.PUntaintNoFailure isNull then Null else NonNull (p.PApplyNoFailure id)
 #else
-    let (|Null|NonNull|) (p:Tainted<'T __withnull>) : Choice> when 'T : __notnull and 'T : not struct =
+    let (|Null|NonNull|) (p:Tainted<'T | null>) : Choice> when 'T : not null and 'T : not struct =
         if p.PUntaintNoFailure isNull then Null else NonNull (p.PApplyNoFailure nonNull)
 #endif
 
diff --git a/src/Compiler/TypedTree/tainted.fsi b/src/Compiler/TypedTree/tainted.fsi
index 8ad58f6f265..61392794b5f 100644
--- a/src/Compiler/TypedTree/tainted.fsi
+++ b/src/Compiler/TypedTree/tainted.fsi
@@ -104,7 +104,7 @@ module internal Tainted =
 #if NO_CHECKNULLS
     val (|Null|NonNull|) : Tainted<'T MaybeNull> -> Choice> when 'T : null and 'T : not struct
 #else
-    val (|Null|NonNull|) : Tainted<'T MaybeNull> -> Choice> when 'T : __notnull and 'T : not struct
+    val (|Null|NonNull|) : Tainted<'T MaybeNull> -> Choice> when 'T : not null and 'T : not struct
 #endif
 
     /// Test whether the tainted value equals given value.
diff --git a/src/Compiler/Utilities/illib.fs b/src/Compiler/Utilities/illib.fs
index 0019262d9c7..65b56386a9c 100644
--- a/src/Compiler/Utilities/illib.fs
+++ b/src/Compiler/Utilities/illib.fs
@@ -62,7 +62,7 @@ module internal PervasiveAutoOpens =
         | null -> raise (ArgumentNullException(paramName))
         | v -> v
 #else
-    type 'T MaybeNull when 'T: __notnull and 'T: not struct = 'T __withnull
+    type 'T MaybeNull when 'T: not null and 'T: not struct = 'T | null
 
 #endif
 
diff --git a/src/Compiler/Utilities/illib.fsi b/src/Compiler/Utilities/illib.fsi
index d7c382c3c53..cdeb8dd276e 100644
--- a/src/Compiler/Utilities/illib.fsi
+++ b/src/Compiler/Utilities/illib.fsi
@@ -45,7 +45,7 @@ module internal PervasiveAutoOpens =
 #else
     /// Indicates that a type may be null. 'MaybeNull' used internally in the F# compiler as unchecked
     /// replacement for 'string?'
-    type 'T MaybeNull when 'T: __notnull and 'T: not struct = 'T __withnull
+    type 'T MaybeNull when 'T: not null and 'T: not struct = 'T | null
 #endif
 
     val inline (===): x: 'a -> y: 'a -> bool when 'a: not struct
diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy
index 7ff2fe76510..4e3ee8d8d2b 100644
--- a/src/Compiler/pars.fsy
+++ b/src/Compiler/pars.fsy
@@ -89,7 +89,7 @@ let parse_error_rich = Some(fun (ctxt: ParseErrorContext<_>) ->
 %token GREATER_RBRACK STRUCT SIG
 %token STATIC MEMBER CLASS ABSTRACT OVERRIDE DEFAULT CONSTRUCTOR INHERIT
 %token EXTERN VOID PUBLIC PRIVATE INTERNAL GLOBAL
-%token MAYBENULL__ NOTNULL__ WITHNULL__ BAR_JUST_BEFORE_NULL
+%token BAR_JUST_BEFORE_NULL
 
 /* for parser 'escape hatch' out of expression context without consuming the 'recover' token */
 %token TYPE_COMING_SOON TYPE_IS_HERE MODULE_COMING_SOON MODULE_IS_HERE
@@ -2587,23 +2587,11 @@ typeConstraint:
 
   | typar COLON NULL
      { SynTypeConstraint.WhereTyparSupportsNull($1, lhs parseState) }
-/*
-** TODO: This rule is not triggering, faking it with __notnull for now
-
-  | typar COLON IDENT NULL
-      { if $3 <> "not" then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier($3 + " (2)"))  
-        SynTypeConstraint.WhereTyparNotSupportsNull($1, lhs parseState) }
-*/
-  | typar COLON NOTNULL__
-      { SynTypeConstraint.WhereTyparNotSupportsNull($1, lhs parseState) }
 
   | typar COLON IDENT NULL
       { if $3 <> "not" then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier($3 + " (2)"))  
         SynTypeConstraint.WhereTyparNotSupportsNull($1, lhs parseState) }
 
-  | typar COLON NOTNULL__
-      { SynTypeConstraint.WhereTyparNotSupportsNull($1, lhs parseState) }
-
   | typar COLON LPAREN classMemberSpfn rparen
      { let tp = $1
        SynTypeConstraint.WhereTyparSupportsMember(SynType.Var(tp, tp.Range), $4, lhs parseState) }
@@ -3111,13 +3099,6 @@ cType:
      { let m = lhs parseState
        SynType.App(SynType.LongIdent(SynLongIdent([ident("nativeptr", m)], [], [ Some(IdentTrivia.OriginalNotation "*") ])), None, [$1], [], None, true, m) }
 
-/*
-  | cType QMARK
-    { SynType.WithNull($1, false, lhs parseState) }
-*/
-  | cType WITHNULL__
-    { SynType.WithNull($1, false, lhs parseState) }
-
   | cType BAR_JUST_BEFORE_NULL NULL
     { SynType.WithNull($1, false, lhs parseState) }
 
@@ -6012,19 +5993,7 @@ appTypeNullableInParens:
     { SynType.Paren($2, lhs parseState) }
 
 appTypeWithoutNull:
-  | appTypeWithoutNull MAYBENULL__
-    { SynType.WithNull($1, true, lhs parseState) }
-
-  | appTypeWithoutNull WITHNULL__
-    { SynType.WithNull($1, false, lhs parseState) }
-
-/*
-  | appTypeWithoutNull QMARK
-    { SynType.WithNull($1, false, lhs parseState) }
-*/
-
   | appTypeWithoutNull arrayTypeSuffix
-
       { SynType.Array($2, $1, lhs parseState) }
 
   | appTypeWithoutNull HIGH_PRECEDENCE_BRACK_APP arrayTypeSuffix /* only HPA for "name[]" allowed here */
diff --git a/src/Compiler/xlf/FSStrings.cs.xlf b/src/Compiler/xlf/FSStrings.cs.xlf
index 0ca74e1ad6f..6b3ebd7d3c6 100644
--- a/src/Compiler/xlf/FSStrings.cs.xlf
+++ b/src/Compiler/xlf/FSStrings.cs.xlf
@@ -67,21 +67,11 @@
         interpolovaný řetězec (část)
         
       
-      
-        keyword '__notnull'
-        keyword '__notnull'
-        
-      
       
         keyword 'while!'
         keyword 'while!'
         
       
-      
-        keyword '__withnull'
-        keyword '__withnull'
-        
-      
       
         . See also {0}.
         . Viz taky {0}.
diff --git a/src/Compiler/xlf/FSStrings.de.xlf b/src/Compiler/xlf/FSStrings.de.xlf
index 5bb910c0b93..70e355f5c10 100644
--- a/src/Compiler/xlf/FSStrings.de.xlf
+++ b/src/Compiler/xlf/FSStrings.de.xlf
@@ -67,21 +67,11 @@
         Interpolierte Zeichenfolge (Teil)
         
       
-      
-        keyword '__notnull'
-        keyword '__notnull'
-        
-      
       
         keyword 'while!'
         keyword 'while!'
         
       
-      
-        keyword '__withnull'
-        keyword '__withnull'
-        
-      
       
         . See also {0}.
         . Siehe auch "{0}".
diff --git a/src/Compiler/xlf/FSStrings.es.xlf b/src/Compiler/xlf/FSStrings.es.xlf
index f930cc3130e..c99ce8e7eec 100644
--- a/src/Compiler/xlf/FSStrings.es.xlf
+++ b/src/Compiler/xlf/FSStrings.es.xlf
@@ -67,21 +67,11 @@
         cadena interpolada (parte)
         
       
-      
-        keyword '__notnull'
-        keyword '__notnull'
-        
-      
       
         keyword 'while!'
         keyword 'while!'
         
       
-      
-        keyword '__withnull'
-        keyword '__withnull'
-        
-      
       
         . See also {0}.
         . Vea también {0}.
diff --git a/src/Compiler/xlf/FSStrings.fr.xlf b/src/Compiler/xlf/FSStrings.fr.xlf
index ee90304b65d..027552d45b5 100644
--- a/src/Compiler/xlf/FSStrings.fr.xlf
+++ b/src/Compiler/xlf/FSStrings.fr.xlf
@@ -67,21 +67,11 @@
         chaîne interpolée (partie)
         
       
-      
-        keyword '__notnull'
-        keyword '__notnull'
-        
-      
       
         keyword 'while!'
         keyword 'while!'
         
       
-      
-        keyword '__withnull'
-        keyword '__withnull'
-        
-      
       
         . See also {0}.
         . Voir aussi {0}.
diff --git a/src/Compiler/xlf/FSStrings.it.xlf b/src/Compiler/xlf/FSStrings.it.xlf
index d533fcf3383..a74a85c49de 100644
--- a/src/Compiler/xlf/FSStrings.it.xlf
+++ b/src/Compiler/xlf/FSStrings.it.xlf
@@ -67,21 +67,11 @@
         stringa interpolata (parte)
         
       
-      
-        keyword '__notnull'
-        keyword '__notnull'
-        
-      
       
         keyword 'while!'
         keyword 'while!'
         
       
-      
-        keyword '__withnull'
-        keyword '__withnull'
-        
-      
       
         . See also {0}.
         . Vedere anche {0}.
diff --git a/src/Compiler/xlf/FSStrings.ja.xlf b/src/Compiler/xlf/FSStrings.ja.xlf
index 3627feb9bf7..65642c3d9c4 100644
--- a/src/Compiler/xlf/FSStrings.ja.xlf
+++ b/src/Compiler/xlf/FSStrings.ja.xlf
@@ -67,21 +67,11 @@
         補間された文字列 (部分)
         
       
-      
-        keyword '__notnull'
-        keyword '__notnull'
-        
-      
       
         keyword 'while!'
         keyword 'while!'
         
       
-      
-        keyword '__withnull'
-        keyword '__withnull'
-        
-      
       
         . See also {0}.
         。{0} も参照してください。
diff --git a/src/Compiler/xlf/FSStrings.ko.xlf b/src/Compiler/xlf/FSStrings.ko.xlf
index fdb8589dc36..f0cc87ebf4f 100644
--- a/src/Compiler/xlf/FSStrings.ko.xlf
+++ b/src/Compiler/xlf/FSStrings.ko.xlf
@@ -67,21 +67,11 @@
         보간 문자열(부분)
         
       
-      
-        keyword '__notnull'
-        keyword '__notnull'
-        
-      
       
         keyword 'while!'
         keyword 'while!'
         
       
-      
-        keyword '__withnull'
-        keyword '__withnull'
-        
-      
       
         . See also {0}.
         {0}도 참조하세요.
diff --git a/src/Compiler/xlf/FSStrings.pl.xlf b/src/Compiler/xlf/FSStrings.pl.xlf
index 612b025b4bc..de0702164be 100644
--- a/src/Compiler/xlf/FSStrings.pl.xlf
+++ b/src/Compiler/xlf/FSStrings.pl.xlf
@@ -67,21 +67,11 @@
         ciąg interpolowany (część)
         
       
-      
-        keyword '__notnull'
-        keyword '__notnull'
-        
-      
       
         keyword 'while!'
         keyword 'while!'
         
       
-      
-        keyword '__withnull'
-        keyword '__withnull'
-        
-      
       
         . See also {0}.
         . Zobacz też {0}.
diff --git a/src/Compiler/xlf/FSStrings.pt-BR.xlf b/src/Compiler/xlf/FSStrings.pt-BR.xlf
index a4f48b46735..058ba47832f 100644
--- a/src/Compiler/xlf/FSStrings.pt-BR.xlf
+++ b/src/Compiler/xlf/FSStrings.pt-BR.xlf
@@ -67,21 +67,11 @@
         cadeia de caracteres interpolada (parte)
         
       
-      
-        keyword '__notnull'
-        keyword '__notnull'
-        
-      
       
         keyword 'while!'
         keyword 'while!'
         
       
-      
-        keyword '__withnull'
-        keyword '__withnull'
-        
-      
       
         . See also {0}.
         . Consulte também {0}.
diff --git a/src/Compiler/xlf/FSStrings.ru.xlf b/src/Compiler/xlf/FSStrings.ru.xlf
index 1c8e749697d..e6117ffcbfa 100644
--- a/src/Compiler/xlf/FSStrings.ru.xlf
+++ b/src/Compiler/xlf/FSStrings.ru.xlf
@@ -67,21 +67,11 @@
         интерполированная строка (часть)
         
       
-      
-        keyword '__notnull'
-        keyword '__notnull'
-        
-      
       
         keyword 'while!'
         keyword 'while!'
         
       
-      
-        keyword '__withnull'
-        keyword '__withnull'
-        
-      
       
         . See also {0}.
         . См. также {0}.
diff --git a/src/Compiler/xlf/FSStrings.tr.xlf b/src/Compiler/xlf/FSStrings.tr.xlf
index 3a7631b488c..72284d16c43 100644
--- a/src/Compiler/xlf/FSStrings.tr.xlf
+++ b/src/Compiler/xlf/FSStrings.tr.xlf
@@ -67,21 +67,11 @@
         düz metin arasına kod eklenmiş dize (parça)
         
       
-      
-        keyword '__notnull'
-        keyword '__notnull'
-        
-      
       
         keyword 'while!'
         keyword 'while!'
         
       
-      
-        keyword '__withnull'
-        keyword '__withnull'
-        
-      
       
         . See also {0}.
         . Ayrıca bkz. {0}.
diff --git a/src/Compiler/xlf/FSStrings.zh-Hans.xlf b/src/Compiler/xlf/FSStrings.zh-Hans.xlf
index baec1f056fe..f3ac19618fa 100644
--- a/src/Compiler/xlf/FSStrings.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSStrings.zh-Hans.xlf
@@ -67,21 +67,11 @@
         内插字符串(部分)
         
       
-      
-        keyword '__notnull'
-        keyword '__notnull'
-        
-      
       
         keyword 'while!'
         keyword 'while!'
         
       
-      
-        keyword '__withnull'
-        keyword '__withnull'
-        
-      
       
         . See also {0}.
         。请参见 {0}。
diff --git a/src/Compiler/xlf/FSStrings.zh-Hant.xlf b/src/Compiler/xlf/FSStrings.zh-Hant.xlf
index cd9bd4799a0..cdaeb244f26 100644
--- a/src/Compiler/xlf/FSStrings.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSStrings.zh-Hant.xlf
@@ -67,21 +67,11 @@
         插補字串 (部分)
         
       
-      
-        keyword '__notnull'
-        keyword '__notnull'
-        
-      
       
         keyword 'while!'
         keyword 'while!'
         
       
-      
-        keyword '__withnull'
-        keyword '__withnull'
-        
-      
       
         . See also {0}.
         。請參閱 {0}。
diff --git a/src/FSharp.Build/FSharpCommandLineBuilder.fs b/src/FSharp.Build/FSharpCommandLineBuilder.fs
index ae783fbcb80..fd886c741d1 100644
--- a/src/FSharp.Build/FSharpCommandLineBuilder.fs
+++ b/src/FSharp.Build/FSharpCommandLineBuilder.fs
@@ -28,7 +28,7 @@ module Utils =
 #else
     /// Indicates that a type may be null. 'MaybeNull' used internally in the F# compiler as unchecked
     /// replacement for 'string?' for example for future FS-1060.
-    type MaybeNull<'T when 'T : __notnull and 'T : not struct> = 'T __withnull
+    type MaybeNull<'T when 'T : not null and 'T : not struct> = 'T | null
 #endif
 
 type FSharpCommandLineBuilder() =
diff --git a/src/FSharp.Core/array.fs b/src/FSharp.Core/array.fs
index d675f714ad9..79b6e7f5f22 100644
--- a/src/FSharp.Core/array.fs
+++ b/src/FSharp.Core/array.fs
@@ -842,7 +842,7 @@ module Array =
         let private createMask<'a>
             (f: 'a -> bool)
             (src: array<'a>)
-            (maskArrayOut: byref __withnull>)
+            (maskArrayOut: byref | null>)
             (leftoverMaskOut: byref)
             =
 #endif
@@ -1038,7 +1038,7 @@ module Array =
 #if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
         let private filterViaMask (maskArray: uint32 array) (leftoverMask: uint32) (count: int) (src: _ array) =
 #else
-        let private filterViaMask (maskArray: uint32 array __withnull) (leftoverMask: uint32) (count: int) (src: _ array) =
+        let private filterViaMask (maskArray: uint32 array | null) (leftoverMask: uint32) (count: int) (src: _ array) =
 #endif
             let dst = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked count
 
diff --git a/src/FSharp.Core/async.fs b/src/FSharp.Core/async.fs
index ce32e7ea3aa..26b1073f05c 100644
--- a/src/FSharp.Core/async.fs
+++ b/src/FSharp.Core/async.fs
@@ -871,7 +871,7 @@ module AsyncPrimitives =
 #if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
     let CreateSwitchToAsync (syncCtxt: SynchronizationContext) =
 #else
-    let CreateSwitchToAsync (syncCtxt: SynchronizationContext __withnull) =
+    let CreateSwitchToAsync (syncCtxt: SynchronizationContext | null) =
 #endif
         MakeAsyncWithCancelCheck(fun ctxt -> ctxt.PostWithTrampoline syncCtxt ctxt.cont)
 
diff --git a/src/FSharp.Core/local.fs b/src/FSharp.Core/local.fs
index effc8e43426..70b1647cb4b 100644
--- a/src/FSharp.Core/local.fs
+++ b/src/FSharp.Core/local.fs
@@ -1089,7 +1089,7 @@ module internal Array =
 #if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
     let stableSortWithKeysAndComparer (cFast:IComparer<'Key>) (c:IComparer<'Key>) (array:'T array) (keys: 'Key array)  =
 #else
-    let stableSortWithKeysAndComparer (cFast:IComparer<'Key> __withnull) (c:IComparer<'Key>) (array:array<'T>) (keys:array<'Key>)  =
+    let stableSortWithKeysAndComparer (cFast:IComparer<'Key> | null) (c:IComparer<'Key>) (array:array<'T>) (keys:array<'Key>)  =
 #endif
         // 'places' is an array or integers storing the permutation performed by the sort        
         let len = array.Length
diff --git a/src/FSharp.Core/option.fs b/src/FSharp.Core/option.fs
index ca3f678852d..9d3e3bd7a3b 100644
--- a/src/FSharp.Core/option.fs
+++ b/src/FSharp.Core/option.fs
@@ -166,13 +166,13 @@ module Option =
         | Some x -> x
 #else
     []
-    let inline ofObj (value: 'T __withnull) : 'T option when 'T: not struct and 'T : __notnull = 
+    let inline ofObj (value: 'T | null) : 'T option when 'T: not struct and 'T : not null = 
         match value with
         | null -> None
         | _ -> Some value
 
     []
-    let inline toObj (value: 'T option) : 'T __withnull when 'T: not struct (* and 'T : __notnull *)  =
+    let inline toObj (value: 'T option) : 'T | null when 'T: not struct (* and 'T : not null *)  =
         match value with
         | None -> null
         | Some x -> x
@@ -344,13 +344,13 @@ module ValueOption =
         | ValueSome x -> x
 #else
     []
-    let inline ofObj (value: 'T __withnull) : 'T voption when 'T: not struct and 'T : __notnull  = 
+    let inline ofObj (value: 'T | null) : 'T voption when 'T: not struct and 'T : not null  = 
         match value with
         | null -> ValueNone
         | _ -> ValueSome value
 
     []
-    let inline toObj (value : 'T voption) : 'T __withnull when 'T: not struct (* and 'T : __notnull *) = 
+    let inline toObj (value : 'T voption) : 'T | null when 'T: not struct (* and 'T : not null *) = 
         match value with
         | ValueNone -> null
         | ValueSome x -> x
diff --git a/src/FSharp.Core/option.fsi b/src/FSharp.Core/option.fsi
index 6b7c7ccd1e5..a3283345317 100644
--- a/src/FSharp.Core/option.fsi
+++ b/src/FSharp.Core/option.fsi
@@ -444,7 +444,7 @@ module Option =
     val inline ofObj: value: 'T -> 'T option  when 'T : null
 #else
     // TODO NULLNESS: assess this change - is it a breaking change?
-    val inline ofObj: value: 'T __withnull -> 'T option  when 'T : __notnull and 'T : not struct
+    val inline ofObj: value: 'T | null -> 'T option  when 'T : not null and 'T : not struct
 #endif
 
     /// Convert an option to a potentially null value.
@@ -464,7 +464,7 @@ module Option =
     val inline toObj: value: 'T option -> 'T when 'T : null
 #else
     // TODO NULLNESS: assess this change - is it a breaking change?
-    val inline toObj: value: 'T option -> 'T __withnull when 'T : not struct (* and 'T : __notnull *)
+    val inline toObj: value: 'T option -> 'T | null when 'T : not struct (* and 'T : not null *)
 #endif
 
 /// Contains operations for working with value options.
@@ -902,7 +902,7 @@ module ValueOption =
     val inline ofObj: value: 'T -> 'T voption  when 'T : null
 #else
     // TODO NULLNESS: assess this change - is it a breaking change?
-    val inline ofObj: value: 'T __withnull -> 'T voption  when 'T : not struct and 'T : __notnull
+    val inline ofObj: value: 'T | null -> 'T voption  when 'T : not struct and 'T : not null
 #endif
 
     /// Convert an option to a potentially null value.
@@ -922,5 +922,5 @@ module ValueOption =
     val inline toObj: value: 'T voption -> 'T when 'T : null
 #else
     // TODO NULLNESS: assess this change - is it a breaking change?
-    val inline toObj: value: 'T voption -> 'T __withnull when 'T : not struct (* and 'T : __notnull *)
+    val inline toObj: value: 'T voption -> 'T | null when 'T : not struct (* and 'T : not null *)
 #endif
diff --git a/src/FSharp.Core/prim-types.fs b/src/FSharp.Core/prim-types.fs
index 6fd50eab510..e2b76c37dab 100644
--- a/src/FSharp.Core/prim-types.fs
+++ b/src/FSharp.Core/prim-types.fs
@@ -4246,7 +4246,7 @@ namespace Microsoft.FSharp.Core
         let inline isNullV (value : Nullable<'T>) = not value.HasValue
 
         []
-        let inline nonNull (value : 'T __withnull when 'T : __notnull and 'T : not struct) = 
+        let inline nonNull (value : 'T | null when 'T : not null and 'T : not struct) = 
             match box value with 
             | null -> raise (NullReferenceException()) 
             | _ -> (# "" value : 'T #)
@@ -4259,7 +4259,7 @@ namespace Microsoft.FSharp.Core
                 raise (NullReferenceException())
 
         []
-        let inline (|Null|NonNull|) (value : 'T __withnull when 'T : __notnull and 'T : not struct) = 
+        let inline (|Null|NonNull|) (value : 'T | null when 'T : not null and 'T : not struct) = 
             match value with 
             | null -> Null () 
             | _ -> NonNull (# "" value : 'T #)
@@ -4270,7 +4270,7 @@ namespace Microsoft.FSharp.Core
             else NullV ()
 
         []
-        let inline (|NonNullQuick|) (value : 'T __withnull when 'T : __notnull and 'T : not struct) =
+        let inline (|NonNullQuick|) (value : 'T | null when 'T : not null and 'T : not struct) =
             match box value with 
             | null -> raise (NullReferenceException()) 
             | _ -> (# "" value : 'T #)
@@ -4281,7 +4281,7 @@ namespace Microsoft.FSharp.Core
             else raise (NullReferenceException()) 
 
         []
-        let inline withNull (value : 'T when 'T : __notnull and 'T : not struct) = (# "" value : 'T __withnull #)
+        let inline withNull (value : 'T when 'T : not null and 'T : not struct) = (# "" value : 'T | null #)
 
         []
         let inline withNullV (value : 'T) : Nullable<'T> = Nullable<'T>(value)
@@ -4290,7 +4290,7 @@ namespace Microsoft.FSharp.Core
         let inline nullV<'T when 'T : struct and 'T : (new : unit -> 'T) and 'T :> ValueType>  = Nullable<'T>()
 
         []
-        let inline nullArgCheck (argumentName:string) (value: 'T __withnull when 'T : __notnull and 'T : not struct) = 
+        let inline nullArgCheck (argumentName:string) (value: 'T | null when 'T : not null and 'T : not struct) = 
             match value with 
             | null -> raise (new ArgumentNullException(argumentName))        
             | _ ->  (# "" value : 'T #)
@@ -4390,7 +4390,7 @@ namespace Microsoft.FSharp.Core
 
 #if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT
         []
-        let inline defaultIfNull defaultValue (arg: 'T __withnull when 'T : __notnull and 'T : not struct) = 
+        let inline defaultIfNull defaultValue (arg: 'T | null when 'T : not null and 'T : not struct) = 
             match arg with null -> defaultValue | _ -> (# "" arg : 'T #)
         
         []
diff --git a/src/FSharp.Core/prim-types.fsi b/src/FSharp.Core/prim-types.fsi
index b59d2f5fc07..401b8e6b4fe 100644
--- a/src/FSharp.Core/prim-types.fsi
+++ b/src/FSharp.Core/prim-types.fsi
@@ -1367,7 +1367,7 @@ namespace Microsoft.FSharp.Core
 #if BUILDING_WITH_LKG || NO_NULLCHECKING_LIB_SUPPORT
         val internal FastGenericComparerCanBeNull<'T>  : System.Collections.Generic.IComparer<'T> when 'T : comparison 
 #else
-        val internal FastGenericComparerCanBeNull<'T>  : System.Collections.Generic.IComparer<'T> __withnull when 'T : comparison 
+        val internal FastGenericComparerCanBeNull<'T>  : System.Collections.Generic.IComparer<'T> | null when 'T : comparison 
 #endif
 
         /// Make an F# hash/equality object for the given type
@@ -3130,7 +3130,7 @@ namespace Microsoft.FSharp.Core
         /// The argument value. If it is null, the defaultValue is returned.
         []
         []
-        val inline defaultIfNull : defaultValue:'T -> arg:'T __withnull -> 'T when 'T : __notnull and 'T : not struct 
+        val inline defaultIfNull : defaultValue:'T -> arg:'T | null -> 'T when 'T : not null and 'T : not struct 
 
         /// Used to specify a default value for an nullable value argument in the implementation of a function
         /// The default value of the argument.
@@ -3444,7 +3444,7 @@ namespace Microsoft.FSharp.Core
         /// A choice indicating whether the value is null or not-null.
         []
         []
-        val inline (|Null|NonNull|) : value: 'T __withnull -> Choice  when 'T : __notnull and 'T : not struct
+        val inline (|Null|NonNull|) : value: 'T | null -> Choice  when 'T : not null and 'T : not struct
         
         /// Determines whether the given value is null.
         /// In a future revision of nullness support this may be unified with 'Null|NonNull'.
@@ -3459,7 +3459,7 @@ namespace Microsoft.FSharp.Core
         /// The non-null value.
         []
         []
-        val inline (|NonNullQuick|) : value: 'T __withnull -> 'T when 'T : __notnull and 'T : not struct
+        val inline (|NonNullQuick|) : value: 'T | null -> 'T when 'T : not null and 'T : not struct
         
         /// When used in a pattern checks the given value is not null.
         /// In a future revision of nullness support this may be unified with 'NonNullQuick'.
@@ -3499,7 +3499,7 @@ namespace Microsoft.FSharp.Core
         /// The value when it is not null. If the value is null an exception is raised.
         []
         []
-        val inline nonNull : value: 'T __withnull -> 'T when 'T : __notnull and 'T : not struct
+        val inline nonNull : value: 'T | null -> 'T when 'T : not null and 'T : not struct
 
         /// Asserts that the value is non-null.
         /// In a future revision of nullness support this may be unified with 'nonNull'.
@@ -3514,7 +3514,7 @@ namespace Microsoft.FSharp.Core
         /// True when value is null, false otherwise.
         []
         []
-        val inline withNull : value:'T -> 'T __withnull when 'T : __notnull and 'T : not struct
+        val inline withNull : value:'T -> 'T | null when 'T : not null and 'T : not struct
 
         /// Asserts that the value is non-null.
         /// In a future revision of nullness support this may be unified with 'withNull'.
@@ -3597,7 +3597,7 @@ namespace Microsoft.FSharp.Core
         /// The result value.
         []
         []
-        val inline nullArgCheck : argumentName:string -> 'T __withnull -> 'T when 'T : __notnull and 'T : not struct
+        val inline nullArgCheck : argumentName:string -> 'T | null -> 'T when 'T : not null and 'T : not struct
 #endif
 
         /// Throw a  exception
diff --git a/src/fsi/console.fs b/src/fsi/console.fs
index a56b3f4e4f7..02e3f4a79c2 100644
--- a/src/fsi/console.fs
+++ b/src/fsi/console.fs
@@ -16,7 +16,7 @@ module internal ConsoleHelpers =
   // Shim to match nullness checking library support in preview
   let inline (|Null|NonNull|) (x: 'T) : Choice = match x with null -> Null | v -> NonNull v
 #else
-  type MaybeNull<'T when 'T : __notnull> = 'T __withnull
+  type MaybeNull<'T when 'T : not null> = 'T | null
 #endif
 
 type internal Style =
diff --git a/tests/adhoc/nullness/enabled/negative.fs b/tests/adhoc/nullness/enabled/negative.fs
index 5722820e23e..3f90d956fe5 100644
--- a/tests/adhoc/nullness/enabled/negative.fs
+++ b/tests/adhoc/nullness/enabled/negative.fs
@@ -1,7 +1,7 @@
 open System
 
 module Basics2 = 
-    let f6 () : 'T __withnull when 'T : not struct and 'T : null = null // Expected to give an error about inconistent constraints
+    let f6 () : 'T | null when 'T : not struct and 'T : null = null // Expected to give an error about inconistent constraints
 
 module NullConstraintTests =
     type C<'T when 'T : null>() = class end
@@ -10,7 +10,7 @@ module NullConstraintTests =
 
     let f2 (y : C>) = y // This gave an error in previous F# and we expect it to continue to give an error
 
-    let f7 (y : C> __withnull) = y // We expect this to give an error
+    let f7 (y : C> | null) = y // We expect this to give an error
 
     module StructExamples = 
 
diff --git a/tests/adhoc/nullness/enabled/positive.fs b/tests/adhoc/nullness/enabled/positive.fs
index 76428ce8355..52f138def42 100644
--- a/tests/adhoc/nullness/enabled/positive.fs
+++ b/tests/adhoc/nullness/enabled/positive.fs
@@ -1,21 +1,21 @@
 module EnabledPositive
 open System
 module Basics =     
-    let x2 : String __withnull = null // expect no warning in any configuration
-    let x3 : String __withnull = "a"  // expect no warning in any configuration
+    let x2 : String | null = null // expect no warning in any configuration
+    let x3 : String | null = "a"  // expect no warning in any configuration
 
 module NotNullConstraint =
-    let f3 (x: 'T when 'T : __notnull) = 1
+    let f3 (x: 'T when 'T : not null) = 1
     let v1 = f3 1 
     let v2 = f3 "a"
     let v3 = f3 (null: obj) // Expect no warning in any configuration - warnings about 'obj' and nulls are suppressed 
-    let v4 = f3 (null: String __withnull) // Expect to give a warning
+    let v4 = f3 (null: String | null) // Expect to give a warning
     let v5 = f3 (Some 1) // Expect to give a warning
 
     let w1 = 1 |> f3
     let w2 = "a" |> f3
     let w3 = (null: obj) |> f3 // Expect no warning in any configuration - warnings about 'obj' and nulls are suppressed 
-    let w4 = (null: String __withnull) |> f3 // Expect to give a warning
+    let w4 = (null: String | null) |> f3 // Expect to give a warning
     let w5 = (Some 1) |> f3 // Expect to give a warning
 
 module MemberBasics = 
@@ -23,7 +23,7 @@ module MemberBasics =
         member x.P = 1
         member x.M() = 2
 
-    let c : C __withnull = C()
+    let c : C | null = C()
     let v1 = c.P  // Expected to give a warning
     let v2 = c.M()  // Expected to give a warning
     let f1 = c.M  // Expected to give a warning
@@ -32,11 +32,11 @@ module MemberBasics =
 module Basics2 = 
     let f1 () = null
 
-    let f2 () : String __withnull = null
+    let f2 () : String | null = null
 
-    let f3 () : 'T __withnull = null
+    let f3 () : 'T | null = null
 
-    let f4 () : 'T __withnull when 'T : not struct = null
+    let f4 () : 'T | null when 'T : not struct = null
 
     let f5 () : 'T when 'T : not struct and 'T : null = null
 
@@ -48,27 +48,27 @@ type C(s: String) =
 
 
 // This give a warning since 'T is not known to be reference type non-null
-let f<'T when 'T: __notnull > (x: 'T __withnull, y: 'T __withnull) = ()
+let f<'T when 'T: not null > (x: 'T | null, y: 'T | null) = ()
 
 module Extractions0c =
 
     let x = null
-    let f<'T when 'T : __notnull> (x: 'T __withnull, y: 'T __withnull) = ()
+    let f<'T when 'T : not null> (x: 'T | null, y: 'T | null) = ()
     let s : String = ""
     let result = f (x, s)   // expect no warning in any configuration
 
 module Extractions0e =
 
     let x = null
-    let f<'T when 'T : __notnull> (x: 'T __withnull, y: 'T __withnull) = ()
+    let f<'T when 'T : not null> (x: 'T | null, y: 'T | null) = ()
     let result = f (x, "") // expect no warning in any configuration
 
 module Extractions1 =
 
-    let mutable x : _ __withnull = null
+    let mutable x : _ | null = null
     x <- ""  // expect no warning
 
-//let f<'T when 'T : not struct> (x: 'T __withnull) = 1
+//let f<'T when 'T : not struct> (x: 'T | null) = 1
 module InteropBasics =
     let s0 = String.Concat("a","b")
     let s1 : String = String.Concat("a","c")
@@ -79,17 +79,17 @@ module InteropBasics =
     let test5 : System.AppDomain  = System.AppDomain.CurrentDomain
 
 type KonsoleWithNulls = 
-    static member WriteLine(s: String __withnull) = Console.WriteLine(s)
-    static member WriteLine(fmt: String __withnull, arg1: String __withnull) = Console.WriteLine(fmt, arg1)
-    static member WriteLine(fmt: String __withnull, [] args: obj __withnull[] __withnull) = Console.WriteLine(fmt, args)
-    static member WriteLineC(s: C __withnull) = Console.WriteLine(s.Value)
-    static member WriteLineC(fmt: C __withnull, arg1: C __withnull) = Console.WriteLine(fmt.Value, arg1.Value)
+    static member WriteLine(s: String | null) = Console.WriteLine(s)
+    static member WriteLine(fmt: String | null, arg1: String | null) = Console.WriteLine(fmt, arg1)
+    static member WriteLine(fmt: String | null, [] args: obj | null[] | null) = Console.WriteLine(fmt, args)
+    static member WriteLineC(s: C | null) = Console.WriteLine(s.Value)
+    static member WriteLineC(fmt: C | null, arg1: C | null) = Console.WriteLine(fmt.Value, arg1.Value)
 
 module KonsoleWithNullsModule = 
-    let WriteLine(s: String __withnull) = Console.WriteLine(s)
-    let WriteLine2(fmt: String __withnull, arg1: String __withnull) = Console.WriteLine(fmt, arg1)
-    let WriteLineC(s: C __withnull) = Console.WriteLine(s.Value)
-    let WriteLineC2(fmt: C __withnull, arg1: C __withnull) = Console.WriteLine(fmt.Value, arg1.Value)
+    let WriteLine(s: String | null) = Console.WriteLine(s)
+    let WriteLine2(fmt: String | null, arg1: String | null) = Console.WriteLine(fmt, arg1)
+    let WriteLineC(s: C | null) = Console.WriteLine(s.Value)
+    let WriteLineC2(fmt: C | null, arg1: C | null) = Console.WriteLine(fmt.Value, arg1.Value)
 
 module KonsoleWithNullsModule2 = 
     let WriteLine x = KonsoleWithNullsModule.WriteLine x
@@ -99,7 +99,7 @@ module KonsoleWithNullsModule2 =
 
 type KonsoleNoNulls = 
     static member WriteLine(s: String) = Console.WriteLine(s)
-    static member WriteLine(fmt: String, arg1: String __withnull) = Console.WriteLine(fmt, arg1)
+    static member WriteLine(fmt: String, arg1: String | null) = Console.WriteLine(fmt, arg1)
     static member WriteLine(fmt: String, [] args: obj[]) = Console.WriteLine(fmt, args)
     static member WriteLineC(s: C) = Console.WriteLine(s.Value)
     static member WriteLineC(fmt: C, arg1: C) = Console.WriteLine(fmt.Value, arg1.Value)
@@ -120,9 +120,9 @@ System.Console.WriteLine("a")
 System.Console.WriteLine("a", (null: obj[])) // Expected to give a Nullness warning
 
 KonsoleWithNulls.WriteLine("Hello world")
-KonsoleWithNulls.WriteLine(null) // WRONG: gives an incorrect Nullness warning for String __withnull and String __withnull
+KonsoleWithNulls.WriteLine(null) // WRONG: gives an incorrect Nullness warning for String | null and String | null
 KonsoleWithNulls.WriteLine("Hello","world")
-KonsoleWithNulls.WriteLine("Hello","world","there") // // WRONG: gives an incorrect Nullness warning for String __withnull and String __withnull
+KonsoleWithNulls.WriteLine("Hello","world","there") // // WRONG: gives an incorrect Nullness warning for String | null and String | null
 
 KonsoleNoNulls.WriteLine("Hello world")
 try 
@@ -171,8 +171,8 @@ with :? System.ArgumentNullException -> ()
 KonsoleNoNulls.WriteLine("Hello","world","there")
 KonsoleWithNulls.WriteLine("Hello","world",null)  // Expected to give a Nullness warning 
 KonsoleNoNulls.WriteLine("Hello","world",null)  // Expected to give a Nullness warning
-System.Console.WriteLine("a", (null: obj[] __withnull)) 
-System.Console.WriteLine("a", (null: obj __withnull[] __withnull))
+System.Console.WriteLine("a", (null: obj[] | null)) 
+System.Console.WriteLine("a", (null: obj | null[] | null))
 
 //-------
 // random stuff
@@ -188,11 +188,11 @@ module NullConstraintTests =
 
     let f3 (y : C) = y // Expect a Nullness warning
 
-    let f4 (y : C) = y // No warning expected 
+    let f4 (y : C) = y // No warning expected 
 
-    let f5 (y : C __withnull>) = y // No warning expected
+    let f5 (y : C | null>) = y // No warning expected
 
-    let f6 (y : C __withnull>) = y // No warning expected, lexing/parsing should succeed 
+    let f6 (y : C | null>) = y // No warning expected, lexing/parsing should succeed 
 
 module DefaultValueTests =
 
@@ -206,17 +206,17 @@ module DefaultValueTests =
         []
         type C3 =
             []
-            val mutable Whoops : String __withnull // expect no warning
+            val mutable Whoops : String | null // expect no warning
 
         []
         type C4b =
             []
-            val mutable Whoops : FSharp.Collections.List __withnull // expect no warning
+            val mutable Whoops : FSharp.Collections.List | null // expect no warning
 
         []
         type C7 =
             []
-            val mutable Whoops : (int -> int) __withnull // expect no warning
+            val mutable Whoops : (int -> int) | null // expect no warning
 
     module ClassExamples = 
 
@@ -226,12 +226,12 @@ module DefaultValueTests =
 
         type C3 =
             []
-            val mutable Whoops : String __withnull // expect no warning
+            val mutable Whoops : String | null // expect no warning
 
         type C4b =
             []
-            val mutable Whoops : int FSharp.Collections.List __withnull // expect no warning
+            val mutable Whoops : int FSharp.Collections.List | null // expect no warning
 
         type C7 =
             []
-            val mutable Whoops : (int -> int) __withnull // expect no warning
+            val mutable Whoops : (int -> int) | null // expect no warning

From 3811c987f1b1b0050906450e2203cfa1708e5561 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Mon, 11 Sep 2023 14:15:42 +0200
Subject: [PATCH 26/59] positive.fs updated

---
 tests/adhoc/nullness/library/positive.fs | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/tests/adhoc/nullness/library/positive.fs b/tests/adhoc/nullness/library/positive.fs
index 6830c8d1e58..77b8c6f7b5a 100644
--- a/tests/adhoc/nullness/library/positive.fs
+++ b/tests/adhoc/nullness/library/positive.fs
@@ -16,7 +16,7 @@ module Library =
 
     let x5 = nonNull "" // Should not give a Nullness warning
     check "ekjnceoiwe5" x5 ""
-    let x6 = nonNull "" // **Expected to give a Nullness warning, expected also to give a warning with nullness checking off
+    let x6 = nonNull "" // **Expected to give a Nullness warning, expected also to give a warning with nullness checking off
     check "ekjnceoiwe6" x6 ""
     let x7 = nonNull ""
     check "ekjnceoiwe7" x7 ""
@@ -35,31 +35,31 @@ module Library =
     check "ekjnceoiwe13" x13 (Nullable())
     let x14 = withNullV 6L
     check "ekjnceoiwe14" x14 (Nullable(6L))
-    let x15 : String __withnull = withNull x4
+    let x15 : String | null = withNull x4
     check "ekjnceoiwe15" x15 ""
-    let x15a : String __withnull = withNull ""
+    let x15a : String | null = withNull ""
     check "ekjnceoiwe15a" x15a ""
-    let x15b : String __withnull = withNull x4
+    let x15b : String | null = withNull x4
     check "ekjnceoiwe15b" x15b ""
-    let x15c : String __withnull = withNull x4 // **Expected to give a Nullness warning
+    let x15c : String | null = withNull x4 // **Expected to give a Nullness warning
     check "ekjnceoiwe15c" x15c ""
     let x16 : Nullable = withNullV 3
     check "ekjnceoiwe16" x16 (Nullable(3))
     
     let y0 = isNull null // Should not give a Nullness warning (obj)
     check "ekjnceoiwey0" y0 true
-    let y1 = isNull (null: obj __withnull) // Should not give a Nullness warning
+    let y1 = isNull (null: obj | null) // Should not give a Nullness warning
     check "ekjnceoiwey1" y1 true
-    let y1b = isNull (null: String __withnull) // Should not give a Nullness warning
+    let y1b = isNull (null: String | null) // Should not give a Nullness warning
     check "ekjnceoiwey1b" y1b true
     let y2 = isNull "" // **Expected to give a Nullness warning - type instantiation of a nullable type is non-nullable String
     check "ekjnceoiwey2" y2 false
     let y9 = isNull "" // **Expected to give a Nullness warning - type instantiation of a nullable type is non-nullable String
     check "ekjnceoiwey9" y9 false
-    let y10 = isNull "" // Should not give a Nullness warning.
+    let y10 = isNull "" // Should not give a Nullness warning.
     check "ekjnceoiwey10" y10 false
     // Not yet allowed 
-    //let f7 () : 'T __withnull when 'T : struct = null
+    //let f7 () : 'T | null when 'T : struct = null
     let f7b () : Nullable<'T> = nullV // BUG: Incorrectly gives a warning about System.ValueType with /test:AssumeNullOnImport
 
     let f0b line = 

From 9edcc7faa2706d85b3c27af96ed0e9e081b7a683 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Mon, 11 Sep 2023 14:20:10 +0200
Subject: [PATCH 27/59] positive.fs paranthesis

---
 micro.exe                                | Bin 0 -> 5120 bytes
 tests/adhoc/nullness/enabled/positive.fs |   4 ++--
 2 files changed, 2 insertions(+), 2 deletions(-)
 create mode 100644 micro.exe

diff --git a/micro.exe b/micro.exe
new file mode 100644
index 0000000000000000000000000000000000000000..d8db3d4211aff6207adc55d71675bd5965c06383
GIT binary patch
literal 5120
zcmeHKPi!1l8UNnQ>}I{L-2{hF2!iQ4rBO=8PGh9jvXixAJ9Xuaovs~;%26^q`@9}9
zJF}fP^5!B4Z|q0YtoL>(Dp-nX0d8Fqq=kk28!p}u9s$s7KBM_x!rnawvWjW
z{h~lrge0Fy-#?GuMk}K+ve6k?+@N&)+|xE1C`b-!%
zeg@OC-!z^v&RqD?1uCAtK=})pxccI>&|b3`H^!V%=kn;~OV6{b90kCCg5~h{iAFKs
zI@)kGiT$vlc*I*+8(yB_l`8!b1Xh)XudmF{pnnhiD)ZApR71}Ib8-EP@AUN{7y7rj
z%yr|O2GDrFb7P);a%1{ngO9F`wXEj_c%6QX<@$&o0-qHR>2WGRRixX(5k>Mf-qiTE
z_z5JNz;IqKjXqXmYhv_IU
zo&jZ`J|kppL(l^|;J8{H5cH-dPjm$6i}bH9#~%C9-U7iiHWR(mrpur|;$=dA8;w1i
z^m}F*n!XoDj@*EjL^f%$_8sXZ)Kp#+2Y!tzG*M05I7wUAaG0IbpN1|)Oe7pdAv{E{!Z?ckWQ!`Y?x)Qz`-0zC?=pu{
zS@6SGoSUhPw_ZxaeGYwfBT8_#yUu3)@=EKjH@!<@IA!c
z5nPucXD91>#mI{9%=m62j8x)#ie_XjZ8T(jBMMiPjJf)I<1<%!r7Lc$g>z$1SB=ux
zlh=@X5~p4=7q~c7nyw#~^;YA%XXksLe)Zj1^GEs~D*WcP)mvX4`}n7Y`&aM$;M8A>
z<9XW@g+k$^(4UvK(#R~(pz$@zpA-Te4wXUECSma=&e=ko`W8-x?BjrrrN00&sDJ;~
z$mtzq2r-yZC(`g<7`+;jsGOe}UtLqY{Z|vI61D2q*CTH=M5RNi)T*|0)|B7ZU4f^M
zX(E>Uy33o-!m)U#TD2$&a(Ws2x~>cyex^ZIp|994gehqIFPy&MGqLl*vVeil5y)N#
z$trx|8al%=87xh*j1xuyR1dVxUxbiNk1~e|j!Vn5%z?aRSpzxL*fPIip2xY2ILWjy
z^X{+9+OH689S8fEWj=16)-mdNF;?FQ?NjaKQ1NMmgL_aHws)BfQ52QEI*aAwRyr#t
zeNMSCBZ9N?CklN+Y`@E;+Ydc85c;b8EVa;SA%~oiM_CNhI%7T2E(;EB!Kb%H=h&Pt
zM(WdRB(T1EG4)J(LAYA@=~Cvfx%WFVEv;qyta?L50E$OwTkQu0E8k|?X6i6>9v;1#
zJJ^D=o3es$Gdpmlbm}-(+OYc++2s!NsQ<55z|ik1n`rw9_+CQaI|XkEqUVl~^SEtB
zJ&=uGKcv!IjApRi-YDY@oUz(+M~tDrMOC^3JWDTunx{p&0e&8M4m88>tWQ484j9dL
z(bYDEeXe8eDnOjZJOcg_ipi&t8t~@hbCU2J(i%k=^G|IzN}b;r)j)I31=vpEMphW#
zgfyTnvJs<%Hw8ZteBkYh_tjowp6xpG92|Xk{FolU1fLPrDJ2il9<pZ#49nb37w}sJK#69YzA_H8C=La7JJno92H#2WoTXGr{LE`M4fD*
zqWjkJG|@lyt>GuX{lmo7&1PV4WG|e_(j{lKWXsTt>bRFDODoHB7oRKHDsjWQ8$_X;
zENw|ux_V`xIN>TKo3&uehJ#Q|meM#JSKhj8y6U1nmHBCP(Tkenu4+0Pmr8ci4gEFT
zj_vnUHXB^ocGuZ_UE&3jZ1qHhe?Smb=r%EZWoxR{3Vct$9~`_NN+X#EJQ!3mAFf5m
zjOW>sw!_>?dMUrK+B_t&d?iJkvW^GV2HrspsgCLOa>uI;*z<#v(o6YmyC64YU8%$GOoFSlI^6llaV8$>4ZMg6Z^zSw+I+8G16HfFueYc;D5RT
RcJ}}HeH`kK;Qy}z{{gg4wQB$X

literal 0
HcmV?d00001

diff --git a/tests/adhoc/nullness/enabled/positive.fs b/tests/adhoc/nullness/enabled/positive.fs
index 52f138def42..3a7afebf6ef 100644
--- a/tests/adhoc/nullness/enabled/positive.fs
+++ b/tests/adhoc/nullness/enabled/positive.fs
@@ -81,7 +81,7 @@ module InteropBasics =
 type KonsoleWithNulls = 
     static member WriteLine(s: String | null) = Console.WriteLine(s)
     static member WriteLine(fmt: String | null, arg1: String | null) = Console.WriteLine(fmt, arg1)
-    static member WriteLine(fmt: String | null, [] args: obj | null[] | null) = Console.WriteLine(fmt, args)
+    static member WriteLine(fmt: String | null, [] args: (obj | null)[] | null) = Console.WriteLine(fmt, args)
     static member WriteLineC(s: C | null) = Console.WriteLine(s.Value)
     static member WriteLineC(fmt: C | null, arg1: C | null) = Console.WriteLine(fmt.Value, arg1.Value)
 
@@ -172,7 +172,7 @@ KonsoleNoNulls.WriteLine("Hello","world","there")
 KonsoleWithNulls.WriteLine("Hello","world",null)  // Expected to give a Nullness warning 
 KonsoleNoNulls.WriteLine("Hello","world",null)  // Expected to give a Nullness warning
 System.Console.WriteLine("a", (null: obj[] | null)) 
-System.Console.WriteLine("a", (null: obj | null[] | null))
+System.Console.WriteLine("a", (null: (obj | null)[] | null))
 
 //-------
 // random stuff

From 60b116839c0ae3687c2d2fe1233d74b526ec9244 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Mon, 11 Sep 2023 14:38:46 +0200
Subject: [PATCH 28/59] fixing "parse warning Remove spaces between the type
 name and type parameter, e.g. "C<'T>", not "C <'T>". Type parameters must be
 placed directly adjacent to the type name."

---
 src/Compiler/SyntaxTree/LexFilter.fs                           | 2 +-
 .../data/SyntaxTree/Nullness/NullAnnotatedExpression.fs.bsl    | 3 ---
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/Compiler/SyntaxTree/LexFilter.fs b/src/Compiler/SyntaxTree/LexFilter.fs
index a4f68b98841..a54b9a20f0a 100644
--- a/src/Compiler/SyntaxTree/LexFilter.fs
+++ b/src/Compiler/SyntaxTree/LexFilter.fs
@@ -1124,7 +1124,7 @@ type LexFilterImpl (
                     //      fx
                     //      fx
                     | DEFAULT | COLON | COLON_GREATER | STRUCT | NULL | DELEGATE | AND | WHEN | AMP
-                    | BAR_JUST_BEFORE_NULL
+                    | BAR_JUST_BEFORE_NULL | BAR
                     | DOT_DOT
                     | NEW
                     | LBRACE_BAR
diff --git a/tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs.bsl b/tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs.bsl
index c29a384e013..ee7ce213156 100644
--- a/tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs.bsl
@@ -63,6 +63,3 @@ ImplFile
           PreXmlDocEmpty, [], None, (1,0--2,0), { LeadingKeyword = None })],
       (true, true), { ConditionalDirectives = []
                       CodeComments = [] }, set []))
-
-(1,23)-(1,48) parse warning Remove spaces between the type name and type parameter, e.g. "C<'T>", not "C <'T>". Type parameters must be placed directly adjacent to the type name.
-(1,18)-(1,56) parse warning Remove spaces between the type name and type parameter, e.g. "C<'T>", not "C <'T>". Type parameters must be placed directly adjacent to the type name.

From ce815cd16858a614c86f4e5c671f5a66db39a267 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Mon, 11 Sep 2023 15:15:35 +0200
Subject: [PATCH 29/59] positive .bsl updated

---
 .../adhoc/nullness/enabled/positive.next.bsl  | 24 ++++++++---
 .../positive.next.enabled.checknulls.bsl      | 40 +++++++++----------
 2 files changed, 38 insertions(+), 26 deletions(-)

diff --git a/tests/adhoc/nullness/enabled/positive.next.bsl b/tests/adhoc/nullness/enabled/positive.next.bsl
index 133a186a32e..ca9680d9aa5 100644
--- a/tests/adhoc/nullness/enabled/positive.next.bsl
+++ b/tests/adhoc/nullness/enabled/positive.next.bsl
@@ -1,12 +1,24 @@
 
-tests\adhoc\nullness\enabled\positive.fs(8,24): warning FS3271: The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+tests\adhoc\nullness\enabled\positive.fs(4,21): error FS0010: Unexpected symbol '|' in binding. Expected '=' or other token.
 
-tests\adhoc\nullness\enabled\positive.fs(51,15): warning FS3271: The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+tests\adhoc\nullness\enabled\positive.fs(5,21): error FS0010: Unexpected symbol '|' in binding. Expected '=' or other token.
 
-tests\adhoc\nullness\enabled\positive.fs(56,19): warning FS3271: The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+tests\adhoc\nullness\enabled\positive.fs(12,31): error FS0010: Unexpected symbol '|' in expression
 
-tests\adhoc\nullness\enabled\positive.fs(63,19): warning FS3271: The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored.
+tests\adhoc\nullness\enabled\positive.fs(18,28): error FS0010: Unexpected symbol '|' in expression
 
-tests\adhoc\nullness\enabled\positive.fs(193,17): error FS0001: The type 'List' does not have 'null' as a proper value
+tests\adhoc\nullness\enabled\positive.fs(26,15): error FS0010: Unexpected symbol '|' in binding. Expected '=' or other token.
 
-tests\adhoc\nullness\enabled\positive.fs(195,17): error FS0001: The type 'List' does not have 'null' as a proper value
+tests\adhoc\nullness\enabled\positive.fs(35,24): error FS0010: Unexpected symbol '|' in binding. Expected '=' or other token.
+
+tests\adhoc\nullness\enabled\positive.fs(37,20): error FS0010: Unexpected symbol '|' in binding. Expected '=' or other token.
+
+tests\adhoc\nullness\enabled\positive.fs(39,20): error FS0010: Unexpected symbol '|' in binding. Expected '=' or other token.
+
+tests\adhoc\nullness\enabled\positive.fs(68,23): error FS0010: Unexpected symbol '|' in binding. Expected '=' or other token.
+
+tests\adhoc\nullness\enabled\positive.fs(84,75): error FS0010: Unexpected symbol '|' in pattern. Expected ',' or other token.
+
+tests\adhoc\nullness\enabled\positive.fs(174,44): error FS0010: Unexpected symbol '|' in expression
+
+tests\adhoc\nullness\enabled\positive.fs(174,51): error FS0010: Unexpected symbol ')' in definition. Expected incomplete structured construct at or before this point or other token.
diff --git a/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl b/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl
index e4f2b0456f8..43b59356de0 100644
--- a/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl
+++ b/tests/adhoc/nullness/enabled/positive.next.enabled.checknulls.bsl
@@ -1,49 +1,49 @@
 
-tests\adhoc\nullness\enabled\positive.fs(12,18): warning FS3261: Nullness warning: The type 'String __withnull' supports 'null' but a non-null type is expected.
+tests\adhoc\nullness\enabled\positive.fs(12,18): warning FS3261: Nullness warning: The type 'String | null' supports 'null' but a non-null type is expected.
 
 tests\adhoc\nullness\enabled\positive.fs(13,18): warning FS3261: Nullness warning: The type ''a option' uses 'null' as a representation value but a non-null type is expected.
 
-tests\adhoc\nullness\enabled\positive.fs(18,43): warning FS3261: Nullness warning: The type 'String __withnull' supports 'null' but a non-null type is expected.
+tests\adhoc\nullness\enabled\positive.fs(18,39): warning FS3261: Nullness warning: The type 'String | null' supports 'null' but a non-null type is expected.
 
 tests\adhoc\nullness\enabled\positive.fs(19,26): warning FS3261: Nullness warning: The type 'int option' uses 'null' as a representation value but a non-null type is expected.
 
-tests\adhoc\nullness\enabled\positive.fs(27,14): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(27,14): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(27,14): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(27,14): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(28,14): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(28,14): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(28,14): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(28,14): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(29,14): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(29,14): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(29,14): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(29,14): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
 tests\adhoc\nullness\enabled\positive.fs(43,26): warning FS3261: Nullness warning: The type 'String' does not support 'null'.
 
-tests\adhoc\nullness\enabled\positive.fs(85,67): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(85,63): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(85,67): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(85,63): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(86,89): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(86,81): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(86,89): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(86,81): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(86,100): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(86,92): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(86,100): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(86,92): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(91,57): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(91,53): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(91,57): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(91,53): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(92,80): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(92,72): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(92,80): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(92,72): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(92,91): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(92,83): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
-tests\adhoc\nullness\enabled\positive.fs(92,91): warning FS3261: Nullness warning: The types 'C' and 'C __withnull' do not have compatible nullability.
+tests\adhoc\nullness\enabled\positive.fs(92,83): warning FS3261: Nullness warning: The types 'C' and 'C | null' do not have compatible nullability.
 
 tests\adhoc\nullness\enabled\positive.fs(120,32): warning FS3261: Nullness warning: The type 'obj array' does not support 'null'.
 

From 4e275ce082c277da27c92a36e56ecd7b757c8a8d Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Mon, 11 Sep 2023 15:26:10 +0200
Subject: [PATCH 30/59] Please mighty fantomas

---
 src/Compiler/Driver/CompilerDiagnostics.fs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs
index 89ea86c44b2..f2ebc1394db 100644
--- a/src/Compiler/Driver/CompilerDiagnostics.fs
+++ b/src/Compiler/Driver/CompilerDiagnostics.fs
@@ -1286,7 +1286,7 @@ type Exception with
                 | Parser.TOKEN_INTERP_STRING_BEGIN_END -> SR.GetString("Parser.TOKEN.INTERP.STRING.BEGIN.END")
                 | Parser.TOKEN_INTERP_STRING_BEGIN_PART -> SR.GetString("Parser.TOKEN.INTERP.STRING.BEGIN.PART")
                 | Parser.TOKEN_INTERP_STRING_PART -> SR.GetString("Parser.TOKEN.INTERP.STRING.PART")
-                | Parser.TOKEN_INTERP_STRING_END -> SR.GetString("Parser.TOKEN.INTERP.STRING.END")              
+                | Parser.TOKEN_INTERP_STRING_END -> SR.GetString("Parser.TOKEN.INTERP.STRING.END")
                 | Parser.TOKEN_BAR_JUST_BEFORE_NULL -> SR.GetString("Parser.TOKEN.BAR_JUST_BEFORE_NULL")
                 | unknown ->
                     let result = sprintf "unknown token tag %+A" unknown

From aa844a41986d1b9223a223f84e4ebbbd7e8941ef Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Mon, 9 Oct 2023 12:04:19 +0200
Subject: [PATCH 31/59] Feature nullness metadata export (#15981)

---
 src/Compiler/AbstractIL/il.fs                 |   13 +-
 src/Compiler/AbstractIL/il.fsi                |    2 +
 src/Compiler/CodeGen/EraseUnions.fs           |  151 ++-
 src/Compiler/CodeGen/IlxGen.fs                |  119 +-
 src/Compiler/CodeGen/IlxGenSupport.fs         |  293 ++++-
 src/Compiler/CodeGen/IlxGenSupport.fsi        |    5 +-
 src/Compiler/TypedTree/TcGlobals.fs           |    6 +
 src/Compiler/TypedTree/TypedTreeOps.fs        |    3 +
 src/Compiler/TypedTree/TypedTreeOps.fsi       |    2 +
 .../EmittedIL/Nullness/AnonRecords.fs         |   14 +
 .../Nullness/AnonRecords.fs.il.net472.bsl     |  846 ++++++++++++++
 .../Nullness/AnonRecords.fs.il.netcore.bsl    |  753 ++++++++++++
 .../EmittedIL/Nullness/CsharpConsumer.cs      |   32 +
 .../EmittedIL/Nullness/CurriedFunctions.fs    |   10 +
 .../Nullness/CurriedFunctions.fs.il.bsl       |  203 ++++
 .../EmittedIL/Nullness/CustomType.fs          |   25 +
 .../EmittedIL/Nullness/CustomType.fs.il.bsl   |  351 ++++++
 .../EmittedIL/Nullness/ModuleLevelBindings.fs |    8 +
 .../Nullness/ModuleLevelBindings.fs.il.bsl    |  230 ++++
 .../Nullness/ModuleLevelFunctions.fs          |   10 +
 .../Nullness/ModuleLevelFunctions.fs.il.bsl   |  214 ++++
 .../Nullness/ModuleLevelFunctionsOpt.fs       |   10 +
 .../ModuleLevelFunctionsOpt.fs.il.bsl         |  211 ++++
 .../EmittedIL/Nullness/NullAsTrueValue.fs     |   33 +
 .../Nullness/NullAsTrueValue.fs.il.net472.bsl | 1040 +++++++++++++++++
 .../NullAsTrueValue.fs.il.netcore.bsl         |  881 ++++++++++++++
 .../EmittedIL/Nullness/NullnessMetadata.fs    |  162 +++
 .../EmittedIL/Nullness/Records.fs             |   25 +
 .../Nullness/Records.fs.il.net472.bsl         |  460 ++++++++
 .../Nullness/Records.fs.il.netcore.bsl        |  367 ++++++
 .../EmittedIL/Nullness/ReferenceDU.fs         |   18 +
 .../Nullness/ReferenceDU.fs.il.net472.bsl     |  772 ++++++++++++
 .../Nullness/ReferenceDU.fs.il.netcore.bsl    |  679 +++++++++++
 .../EmittedIL/Nullness/StructDU.fs            |   13 +
 .../Nullness/StructDU.fs.il.net472.bsl        |  574 +++++++++
 .../Nullness/StructDU.fs.il.netcore.bsl       |  415 +++++++
 .../FSharp.Compiler.ComponentTests.fsproj     |    1 +
 tests/adhoc/nullness/out.fsi                  |  346 ++++++
 38 files changed, 9212 insertions(+), 85 deletions(-)
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.net472.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.netcore.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CsharpConsumer.cs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.net472.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.netcore.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.net472.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.netcore.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.net472.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.netcore.bsl
 create mode 100644 tests/adhoc/nullness/out.fsi

diff --git a/src/Compiler/AbstractIL/il.fs b/src/Compiler/AbstractIL/il.fs
index 2c96d10f528..becb0c3f46d 100644
--- a/src/Compiler/AbstractIL/il.fs
+++ b/src/Compiler/AbstractIL/il.fs
@@ -3412,6 +3412,11 @@ type ILGlobals(primaryScopeRef: ILScopeRef, equivPrimaryAssemblyRefs: ILAssembly
 
     let mkSysILTypeRef nm = mkILTyRef (primaryScopeRef, nm)
 
+    let byteIlType = ILType.Value(mkILNonGenericTySpec (mkSysILTypeRef tname_Byte))
+
+    let stringIlType =
+        mkILBoxedType (mkILNonGenericTySpec (mkSysILTypeRef tname_String))
+
     member _.primaryAssemblyScopeRef = primaryScopeRef
 
     member x.primaryAssemblyRef =
@@ -3429,7 +3434,7 @@ type ILGlobals(primaryScopeRef: ILScopeRef, equivPrimaryAssemblyRefs: ILAssembly
 
     member val typ_Object = mkILBoxedType (mkILNonGenericTySpec (mkSysILTypeRef tname_Object))
 
-    member val typ_String = mkILBoxedType (mkILNonGenericTySpec (mkSysILTypeRef tname_String))
+    member val typ_String = stringIlType
 
     member val typ_Array = mkILBoxedType (mkILNonGenericTySpec (mkSysILTypeRef tname_Array))
 
@@ -3443,7 +3448,11 @@ type ILGlobals(primaryScopeRef: ILScopeRef, equivPrimaryAssemblyRefs: ILAssembly
 
     member val typ_Int64 = ILType.Value(mkILNonGenericTySpec (mkSysILTypeRef tname_Int64))
 
-    member val typ_Byte = ILType.Value(mkILNonGenericTySpec (mkSysILTypeRef tname_Byte))
+    member val typ_Byte = byteIlType
+
+    member val typ_ByteArray = ILType.Array(ILArrayShape.SingleDimensional, byteIlType)
+
+    member val typ_StringArray = ILType.Array(ILArrayShape.SingleDimensional, stringIlType)
 
     member val typ_UInt16 = ILType.Value(mkILNonGenericTySpec (mkSysILTypeRef tname_UInt16))
 
diff --git a/src/Compiler/AbstractIL/il.fsi b/src/Compiler/AbstractIL/il.fsi
index 34e7d8584e2..b5cf43d628c 100644
--- a/src/Compiler/AbstractIL/il.fsi
+++ b/src/Compiler/AbstractIL/il.fsi
@@ -1876,11 +1876,13 @@ type internal ILGlobals =
     member typ_Enum: ILType
     member typ_Object: ILType
     member typ_String: ILType
+    member typ_StringArray: ILType
     member typ_Type: ILType
     member typ_Array: ILType
     member typ_IntPtr: ILType
     member typ_UIntPtr: ILType
     member typ_Byte: ILType
+    member typ_ByteArray: ILType
     member typ_Int16: ILType
     member typ_Int32: ILType
     member typ_Int64: ILType
diff --git a/src/Compiler/CodeGen/EraseUnions.fs b/src/Compiler/CodeGen/EraseUnions.fs
index d00c45f2df7..fd0d9660914 100644
--- a/src/Compiler/CodeGen/EraseUnions.fs
+++ b/src/Compiler/CodeGen/EraseUnions.fs
@@ -8,6 +8,7 @@ open FSharp.Compiler.IlxGenSupport
 open System.Collections.Generic
 open System.Reflection
 open Internal.Utilities.Library
+open FSharp.Compiler.TypedTreeOps
 open FSharp.Compiler.TcGlobals
 open FSharp.Compiler.AbstractIL.IL
 open FSharp.Compiler.AbstractIL.ILX.Types
@@ -665,6 +666,7 @@ let emitDataSwitch ilg (cg: ICodeGen<'Mark>) (avoidHelpers, cuspec, cases) =
 
 let mkMethodsAndPropertiesForFields
     (addMethodGeneratedAttrs, addPropertyGeneratedAttrs)
+    (g: TcGlobals)
     access
     attr
     imports
@@ -704,15 +706,28 @@ let mkMethodsAndPropertiesForFields
             for field in fields do
                 let fspec = mkILFieldSpecInTy (ilTy, field.LowerName, field.Type)
 
+                let ilReturn = mkILReturn field.Type
+
+                let ilReturn =
+                    if TryFindILAttribute g.attrib_NullableAttribute field.ILField.CustomAttrs then
+                        let attrs =
+                            field.ILField.CustomAttrs.AsArray()
+                            |> Array.filter (IsILAttrib g.attrib_NullableAttribute)
+
+                        ilReturn.WithCustomAttrs(mkILCustomAttrsFromArray attrs)
+                    else
+                        ilReturn
+
                 yield
                     mkILNonGenericInstanceMethod (
                         "get_" + adjustFieldName hasHelpers field.Name,
                         access,
                         [],
-                        mkILReturn field.Type,
+                        ilReturn,
                         mkMethodBody (true, [], 2, nonBranchingInstrsToCode [ mkLdarg 0us; mkNormalLdfld fspec ], attr, imports)
                     )
                     |> addMethodGeneratedAttrs
+
         ]
 
     basicProps, basicMethods
@@ -801,8 +816,34 @@ let convAlternativeDef
                 elif repr.RepresentOneAlternativeAsNull info then
                     [], []
                 else
+                    let additionalAttributes =
+                        if
+                            g.checkNullness
+                            && g.langFeatureNullness
+                            && repr.RepresentAlternativeAsStructValue info
+                            && not alt.IsNullary
+                        then
+                            let notnullfields =
+                                alt.FieldDefs
+                                // Fields that are nullable even from F# perspective has an [Nullable] attribute on them
+                                // Non-nullable fields are implicit in F#, therefore not annotated separately
+                                |> Array.filter (fun f -> TryFindILAttribute g.attrib_NullableAttribute f.ILField.CustomAttrs |> not)
+
+                            let fieldNames =
+                                notnullfields
+                                |> Array.map (fun f -> f.LowerName)
+                                |> Array.append (notnullfields |> Array.map (fun f -> f.Name))
+
+                            if fieldNames |> Array.isEmpty then
+                                emptyILCustomAttrs
+                            else
+                                mkILCustomAttrsFromArray [| GetNotNullWhenTrueAttribute g fieldNames |]
+
+                        else
+                            emptyILCustomAttrs
+
                     [
-                        mkILNonGenericInstanceMethod (
+                        (mkILNonGenericInstanceMethod (
                             "get_" + mkTesterName altName,
                             cud.HelpersAccessibility,
                             [],
@@ -815,7 +856,8 @@ let convAlternativeDef
                                 attr,
                                 imports
                             )
-                        )
+                        ))
+                            .With(customAttrs = additionalAttributes)
                         |> addMethodGeneratedAttrs
                     ],
                     [
@@ -838,7 +880,7 @@ let convAlternativeDef
                             propertyType = g.ilg.typ_Bool,
                             init = None,
                             args = [],
-                            customAttrs = emptyILCustomAttrs
+                            customAttrs = additionalAttributes
                         )
                         |> addPropertyGeneratedAttrs
                         |> addPropertyNeverAttrs
@@ -847,13 +889,24 @@ let convAlternativeDef
             let baseMakerMeths, baseMakerProps =
 
                 if alt.IsNullary then
+                    let attributes =
+                        if
+                            g.checkNullness
+                            && g.langFeatureNullness
+                            && repr.RepresentAlternativeAsNull(info, alt)
+                        then
+                            GetNullableAttribute g [ FSharp.Compiler.TypedTree.NullnessInfo.WithNull ]
+                            |> Array.singleton
+                            |> mkILCustomAttrsFromArray
+                        else
+                            emptyILCustomAttrs
 
                     let nullaryMeth =
                         mkILNonGenericStaticMethod (
                             "get_" + altName,
                             cud.HelpersAccessibility,
                             [],
-                            mkILReturn baseTy,
+                            (mkILReturn baseTy).WithCustomAttrs attributes,
                             mkMethodBody (
                                 true,
                                 [],
@@ -877,7 +930,7 @@ let convAlternativeDef
                             propertyType = baseTy,
                             init = None,
                             args = [],
-                            customAttrs = emptyILCustomAttrs
+                            customAttrs = attributes
                         )
                         |> addPropertyGeneratedAttrs
                         |> addPropertyNeverAttrs
@@ -921,7 +974,19 @@ let convAlternativeDef
                             mkMakerName cuspec altName,
                             cud.HelpersAccessibility,
                             fields
-                            |> Array.map (fun fd -> mkILParamNamed (fd.LowerName, fd.Type))
+                            |> Array.map (fun fd ->
+                                let plainParam = mkILParamNamed (fd.LowerName, fd.Type)
+
+                                if TryFindILAttribute g.attrib_NullableAttribute fd.ILField.CustomAttrs then
+                                    let attrs =
+                                        fd.ILField.CustomAttrs.AsArray()
+                                        |> Array.filter (IsILAttrib g.attrib_NullableAttribute)
+
+                                    { plainParam with
+                                        CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrsFromArray attrs)
+                                    }
+                                else
+                                    plainParam)
                             |> Array.toList,
                             mkILReturn baseTy,
                             mkMethodBody (true, locals, fields.Length + locals.Length, nonBranchingInstrsToCode ilInstrs, attr, imports)
@@ -1090,6 +1155,7 @@ let convAlternativeDef
                         let basicProps, basicMethods =
                             mkMethodsAndPropertiesForFields
                                 (addMethodGeneratedAttrs, addPropertyGeneratedAttrs)
+                                g
                                 cud.UnionCasesAccessibility
                                 attr
                                 imports
@@ -1123,6 +1189,12 @@ let convAlternativeDef
                                 .With(customAttrs = mkILCustomAttrs [ GetDynamicDependencyAttribute g 0x660 baseTy ])
                             |> addMethodGeneratedAttrs
 
+                        let attrs =
+                            if g.checkNullness && g.langFeatureNullness then
+                                GetNullableContextAttribute g :: debugAttrs
+                            else
+                                debugAttrs
+
                         let altTypeDef =
                             mkILGenericClass (
                                 altTy.TypeSpec.Name,
@@ -1141,7 +1213,7 @@ let convAlternativeDef
                                 emptyILTypeDefs,
                                 mkILProperties basicProps,
                                 emptyILEvents,
-                                mkILCustomAttrs debugAttrs,
+                                mkILCustomAttrs attrs,
                                 ILTypeInit.BeforeField
                             )
 
@@ -1261,15 +1333,67 @@ let mkClassUnionDef
                                 |> addMethodGeneratedAttrs
                             ]
 
+                    let fieldDefs =
+                        // Since structs are flattened out for all cases together, all boxed fields are potentially nullable
+                        if
+                            isStruct
+                            && cud.UnionCases.Length > 1
+                            && g.checkNullness
+                            && g.langFeatureNullness
+                        then
+                            alt.FieldDefs
+                            |> Array.map (fun field ->
+                                if field.Type.IsNominal && field.Type.Boxity = AsValue then
+                                    field
+                                else
+                                    let attrs =
+                                        let existingAttrs = field.ILField.CustomAttrs.AsArray()
+
+                                        let nullableIdx =
+                                            existingAttrs |> Array.tryFindIndex (IsILAttrib g.attrib_NullableAttribute)
+
+                                        match nullableIdx with
+                                        | None ->
+                                            existingAttrs
+                                            |> Array.append [| GetNullableAttribute g [ FSharp.Compiler.TypedTree.NullnessInfo.WithNull ] |]
+                                        | Some idx ->
+                                            let replacementAttr =
+                                                match existingAttrs[idx] with
+                                                (*
+                                                 The attribute carries either a single byte, or a list of bytes for the fields itself and all its generic type arguments
+                                                 The way we lay out DUs does not affect nullability of the typars of a field, therefore we just change the very first byte
+                                                 If the field was already declared as nullable (value = 2uy) or ambivalent(value = 0uy), we can keep it that way
+                                                 If it was marked as non-nullable within that UnionCase, we have to convert it to WithNull (2uy) due to other cases being possible
+                                                *)
+                                                | Encoded (method, _data, [ ILAttribElem.Byte 1uy ]) ->
+                                                    mkILCustomAttribMethRef (method, [ ILAttribElem.Byte 2uy ], [])
+                                                | Encoded (method,
+                                                           _data,
+                                                           [ ILAttribElem.Array (elemType, (ILAttribElem.Byte 1uy) :: otherElems) ]) ->
+                                                    mkILCustomAttribMethRef (
+                                                        method,
+                                                        [ ILAttribElem.Array(elemType, (ILAttribElem.Byte 2uy) :: otherElems) ],
+                                                        []
+                                                    )
+                                                | attrAsBefore -> attrAsBefore
+
+                                            existingAttrs |> Array.replace idx replacementAttr
+
+                                    field.ILField.With(customAttrs = mkILCustomAttrsFromArray attrs)
+                                    |> IlxUnionCaseField)
+                        else
+                            alt.FieldDefs
+
                     let props, meths =
                         mkMethodsAndPropertiesForFields
                             (addMethodGeneratedAttrs, addPropertyGeneratedAttrs)
+                            g
                             cud.UnionCasesAccessibility
                             cud.DebugPoint
                             cud.DebugImports
                             cud.HasHelpers
                             baseTy
-                            alt.FieldDefs
+                            fieldDefs
 
                     yield (fields, (ctor @ meths), props)
         ]
@@ -1467,7 +1591,14 @@ let mkClassUnionDef
                         @ List.map (fun (_, _, _, _, fdef, _) -> fdef) altNullaryFields
                           @ td.Fields.AsList()
                     ),
-                properties = mkILProperties (tagProps @ basePropsFromAlt @ selfProps @ existingProps)
+                properties = mkILProperties (tagProps @ basePropsFromAlt @ selfProps @ existingProps),
+                customAttrs =
+                    if cud.IsNullPermitted && g.checkNullness && g.langFeatureNullness then
+                        td.CustomAttrs.AsArray()
+                        |> Array.append [| GetNullableAttribute g [ FSharp.Compiler.TypedTree.NullnessInfo.WithNull ] |]
+                        |> mkILCustomAttrsFromArray
+                    else
+                        td.CustomAttrs
             )
         // The .cctor goes on the Cases type since that's where the constant fields for nullary constructors live
         |> addConstFieldInit
diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs
index 33b39ce7f73..cbf129b653c 100644
--- a/src/Compiler/CodeGen/IlxGen.fs
+++ b/src/Compiler/CodeGen/IlxGen.fs
@@ -693,15 +693,11 @@ and GenUnionCaseRef (cenv: cenv) m tyenv i (fspecs: RecdField[]) =
         let ilFieldDef =
             mkILInstanceField (fspec.LogicalName, GenType cenv m tyenv fspec.FormalType, None, ILMemberAccess.Public)
         // These properties on the "field" of an alternative end up going on a property generated by cu_erase.fs
-        IlxUnionCaseField(
-            ilFieldDef.With(
-                customAttrs =
-                    mkILCustomAttrs
-                        [
-                            (mkCompilationMappingAttrWithVariantNumAndSeqNum g (int SourceConstructFlags.Field) i j)
-                        ]
-            )
-        ))
+        let attrs =
+            (mkCompilationMappingAttrWithVariantNumAndSeqNum g (int SourceConstructFlags.Field) i j)
+            :: GenAdditionalAttributesForTy g fspec.FormalType
+
+        IlxUnionCaseField(ilFieldDef.With(customAttrs = mkILCustomAttrs attrs)))
 
 and GenUnionRef (cenv: cenv) m (tcref: TyconRef) =
     let g = cenv.g
@@ -1868,13 +1864,30 @@ type TypeDefBuilder(tdef: ILTypeDef, tdefDiscards) =
     let gevents = ResizeArray(tdef.Events.AsList())
     let gnested = TypeDefsBuilder()
 
-    member _.Close() =
+    member _.Close(g: TcGlobals) =
+
+        let attrs =
+            if g.checkNullness && g.langFeatureNullness then
+                let attrsBefore = tdef.CustomAttrs
+
+                [|
+                    yield! attrsBefore.AsArray()
+                    if attrsBefore |> TryFindILAttribute g.attrib_AllowNullLiteralAttribute then
+                        yield GetNullableAttribute g [ NullnessInfo.WithNull ]
+                    if (gmethods.Count + gfields.Count + gproperties.Count) > 0 then
+                        yield GetNullableContextAttribute g
+                |]
+                |> mkILCustomAttrsFromArray
+            else
+                tdef.CustomAttrs
+
         tdef.With(
             methods = mkILMethods (ResizeArray.toList gmethods),
             fields = mkILFields (ResizeArray.toList gfields),
             properties = mkILProperties (tdef.Properties.AsList() @ HashRangeSorted gproperties),
             events = mkILEvents (ResizeArray.toList gevents),
-            nestedTypes = mkILTypeDefs (tdef.NestedTypes.AsList() @ gnested.Close())
+            nestedTypes = mkILTypeDefs (tdef.NestedTypes.AsList() @ gnested.Close(g)),
+            customAttrs = attrs
         )
 
     member _.AddEventDef edef = gevents.Add edef
@@ -1922,14 +1935,14 @@ and TypeDefsBuilder() =
     let mutable countDown = System.Int32.MaxValue
     let mutable countUp = -1
 
-    member b.Close() =
+    member b.Close(g: TcGlobals) =
         //The order we emit type definitions is not deterministic since it is using the reverse of a range from a hash table. We should use an approximation of source order.
         // Ideally it shouldn't matter which order we use.
         // However, for some tests FSI generated code appears sensitive to the order, especially for nested types.
 
         [
             for _, (b, eliminateIfEmpty) in tdefs.Values |> Seq.collect id |> Seq.sortBy fst do
-                let tdef = b.Close()
+                let tdef = b.Close(g)
                 // Skip the  type if it is empty
                 if
                     not eliminateIfEmpty
@@ -2359,7 +2372,7 @@ and AssemblyBuilder(cenv: cenv, anonTypeTable: AnonTypeGenerationTable) as mgbuf
             |> List.sortBy (fst >> (~-)) // invert the result to get 'order-by-descending' behavior (items in list are 0..* so we don't need to worry about int.MinValue)
             |> List.map snd
 
-        gtdefs.Close(), orderedReflectedDefinitions
+        gtdefs.Close(g), orderedReflectedDefinitions
 
     member _.cenv = cenv
 
@@ -5565,6 +5578,24 @@ and GenGenericParam cenv eenv (tp: Typar) =
             | TyparConstraint.IsNonNullableStruct _ -> true
             | _ -> false)
 
+    let notNullReferenceTypeConstraint =
+        if g.langFeatureNullness && g.checkNullness then
+            let hasNotSupportsNull =
+                tp.Constraints
+                |> List.exists (function
+                    | TyparConstraint.NotSupportsNull _ -> true
+                    | _ -> false)
+
+            if hasNotSupportsNull || notNullableValueTypeConstraint then
+                NullnessInfo.WithoutNull
+            elif hasNotSupportsNull || refTypeConstraint then
+                NullnessInfo.WithNull
+            else
+                NullnessInfo.AmbivalentToNull
+            |> Some
+        else
+            None
+
     let defaultConstructorConstraint =
         tp.Constraints
         |> List.exists (function
@@ -5606,12 +5637,14 @@ and GenGenericParam cenv eenv (tp: Typar) =
             nm
 
     let attributeList =
-        let defined = GenAttrs cenv eenv tp.Attribs
-
-        if emitUnmanagedInIlOutput then
-            (GetIsUnmanagedAttribute g) :: defined
-        else
-            defined
+        [
+            yield! GenAttrs cenv eenv tp.Attribs
+            if emitUnmanagedInIlOutput then
+                yield (GetIsUnmanagedAttribute g)
+            match notNullReferenceTypeConstraint with
+            | Some nullInfo -> yield GetNullableAttribute g [ nullInfo ]
+            | _ -> ()
+        ]
 
     let tpAttrs = mkILCustomAttrs (attributeList)
 
@@ -5646,11 +5679,7 @@ and GenSlotParam m cenv eenv slotParam : ILParameter =
         GenParamAttribs cenv ty attribs
 
     let ilAttribs = GenAttrs cenv eenv attribs
-
-    let ilAttribs =
-        match GenReadOnlyAttributeIfNecessary cenv.g ty with
-        | Some attr -> ilAttribs @ [ attr ]
-        | None -> ilAttribs
+    let ilAttribs = ilAttribs @ GenAdditionalAttributesForTy cenv.g ty
 
     {
         Name = nm
@@ -5706,9 +5735,9 @@ and GenFormalReturnType m cenv eenvFormal returnTy : ILReturn =
     match returnTy with
     | None -> ilRet
     | Some ty ->
-        match GenReadOnlyAttributeIfNecessary cenv.g ty with
-        | Some attr -> ilRet.WithCustomAttrs(mkILCustomAttrs (ilRet.CustomAttrs.AsList() @ [ attr ]))
-        | None -> ilRet
+        match GenAdditionalAttributesForTy cenv.g ty with
+        | [] -> ilRet
+        | attrs -> ilRet.WithCustomAttrs(mkILCustomAttrs (ilRet.CustomAttrs.AsList() @ attrs))
 
 and instSlotParam inst (TSlotParam (nm, ty, inFlag, fl2, fl3, attrs)) =
     TSlotParam(nm, instType inst ty, inFlag, fl2, fl3, attrs)
@@ -8334,7 +8363,7 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv bind isStateVar startMarkOpt =
                 propertyType = ilTy,
                 init = None,
                 args = [],
-                customAttrs = mkILCustomAttrs ilAttribs
+                customAttrs = mkILCustomAttrs (GenAdditionalAttributesForTy g vspec.Type @ ilAttribs)
             )
 
         cgbuf.mgbuf.AddOrMergePropertyDef(ilGetterMethSpec.MethodRef.DeclaringTypeRef, ilPropDef, m)
@@ -8410,6 +8439,8 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv bind isStateVar startMarkOpt =
                 else
                     GenAttrs cenv eenv vspec.Attribs // literals have no property, so preserve all the attributes on the field itself
 
+            let ilAttribs = GenAdditionalAttributesForTy g vspec.Type @ ilAttribs
+
             let ilFieldDef =
                 ilFieldDef.With(customAttrs = mkILCustomAttrs (ilAttribs @ [ g.DebuggerBrowsableNeverAttribute ]))
 
@@ -8431,6 +8462,7 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv bind isStateVar startMarkOpt =
                 vspec.Attribs
                 |> List.filter (fun (Attrib (_, _, _, _, _, targets, _)) -> canTarget (targets, System.AttributeTargets.Property))
                 |> GenAttrs cenv eenv // property only gets attributes that target properties
+                |> List.append (GenAdditionalAttributesForTy g vspec.Type)
 
             let ilPropDef =
                 ILPropertyDef(
@@ -8751,11 +8783,7 @@ and GenParams
                 | None -> None, takenNames
 
             let ilAttribs = GenAttrs cenv eenv attribs
-
-            let ilAttribs =
-                match GenReadOnlyAttributeIfNecessary cenv.g methodArgTy with
-                | Some attr -> ilAttribs @ [ attr ]
-                | None -> ilAttribs
+            let ilAttribs = ilAttribs @ GenAdditionalAttributesForTy cenv.g methodArgTy
 
             let param: ILParameter =
                 {
@@ -8781,10 +8809,7 @@ and GenReturnInfo cenv eenv returnTy ilRetTy (retInfo: ArgReprInfo) : ILReturn =
 
     let ilAttribs =
         match returnTy with
-        | Some retTy ->
-            match GenReadOnlyAttributeIfNecessary cenv.g retTy with
-            | Some attr -> ilAttribs @ [ attr ]
-            | None -> ilAttribs
+        | Some retTy -> ilAttribs @ GenAdditionalAttributesForTy cenv.g retTy
         | _ -> ilAttribs
 
     let ilAttrs = mkILCustomAttrs ilAttribs
@@ -9119,9 +9144,7 @@ and GenMethodForBinding
                 || memberInfo.MemberFlags.MemberKind = SynMemberKind.PropertySet
                 || memberInfo.MemberFlags.MemberKind = SynMemberKind.PropertyGetSet
                 ->
-                match GenReadOnlyAttributeIfNecessary cenv.g returnTy with
-                | Some ilAttr -> ilAttr
-                | _ -> ()
+                yield! GenAdditionalAttributesForTy cenv.g returnTy
             | _ -> ()
         ]
 
@@ -10328,6 +10351,8 @@ and GenWitnessParams cenv eenv m (witnessInfos: TraitWitnessInfos) =
         let nm = String.uncapitalize witnessInfo.MemberName
         let nm = if used.Contains nm then nm + string i else nm
 
+        let attribs = GenAdditionalAttributesForTy cenv.g ty
+
         let ilParam: ILParameter =
             {
                 Name = Some nm
@@ -10337,7 +10362,7 @@ and GenWitnessParams cenv eenv m (witnessInfos: TraitWitnessInfos) =
                 IsIn = false
                 IsOut = false
                 IsOptional = false
-                CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs [])
+                CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs attribs)
                 MetadataIndex = NoMetadataIdx
             }
 
@@ -10369,9 +10394,7 @@ and GenAbstractBinding cenv eenv tref (vref: ValRef) =
                     || memberInfo.MemberFlags.MemberKind = SynMemberKind.PropertySet
                     || memberInfo.MemberFlags.MemberKind = SynMemberKind.PropertyGetSet
                     ->
-                    match GenReadOnlyAttributeIfNecessary cenv.g returnTy with
-                    | Some ilAttr -> ilAttr
-                    | _ -> ()
+                    yield! GenAdditionalAttributesForTy cenv.g returnTy
                 | _ -> ()
             ]
 
@@ -10825,7 +10848,11 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) =
                                 literalValue = None,
                                 offset = ilFieldOffset,
                                 marshal = None,
-                                customAttrs = mkILCustomAttrs (GenAttrs cenv eenv fattribs @ extraAttribs)
+                                customAttrs =
+                                    mkILCustomAttrs (
+                                        GenAttrs cenv eenv fattribs
+                                        @ extraAttribs @ GenAdditionalAttributesForTy g fspec.FormalType
+                                    )
                             )
                                 .WithAccess(access)
                                 .WithStatic(isStatic)
diff --git a/src/Compiler/CodeGen/IlxGenSupport.fs b/src/Compiler/CodeGen/IlxGenSupport.fs
index 6fd2074c4e6..3fcd1821a35 100644
--- a/src/Compiler/CodeGen/IlxGenSupport.fs
+++ b/src/Compiler/CodeGen/IlxGenSupport.fs
@@ -8,6 +8,7 @@ open Internal.Utilities.Library
 open FSharp.Compiler.AbstractIL.IL
 open FSharp.Compiler.TcGlobals
 open FSharp.Compiler.TypedTreeOps
+open FSharp.Compiler.TypedTree
 
 /// Make a method that simply loads a field
 let mkLdfldMethodDef (ilMethName, iLAccess, isStatic, ilTy, ilFieldName, ilPropType, customAttrs) =
@@ -66,7 +67,22 @@ let mkILNonGenericInstanceProperty (name, ilType, propertyAttribute, customAttri
         customAttrs = customAttributes
     )
 
-let mkLocalPrivateAttributeWithPropertyConstructors (g: TcGlobals, name: string, attrProperties: (string * ILType) list option) =
+type AttrDataGenerationStyle =
+    | PublicFields
+    | EncapsulatedProperties
+
+let getFieldMemberAccess =
+    function
+    | PublicFields -> ILMemberAccess.Public
+    | EncapsulatedProperties -> ILMemberAccess.Private
+
+let mkLocalPrivateAttributeWithPropertyConstructors
+    (
+        g: TcGlobals,
+        name: string,
+        attrProperties: (string * ILType) list option,
+        codegenStyle: AttrDataGenerationStyle
+    ) =
     let ilTypeRef = mkILTyRef (ILScopeRef.Local, name)
     let ilTy = mkILFormalNamedTy ILBoxity.AsObject ilTypeRef []
 
@@ -74,21 +90,34 @@ let mkLocalPrivateAttributeWithPropertyConstructors (g: TcGlobals, name: string,
         attrProperties
         |> Option.defaultValue []
         |> List.map (fun (name, ilType) ->
-            let fieldName = name + "@"
-
-            (g.AddFieldGeneratedAttributes(mkILInstanceField (fieldName, ilType, None, ILMemberAccess.Private))),
-            (g.AddMethodGeneratedAttributes(mkLdfldMethodDef ($"get_{name}", ILMemberAccess.Public, false, ilTy, fieldName, ilType, []))),
-            (g.AddPropertyGeneratedAttributes(
-                mkILNonGenericInstanceProperty (
-                    name,
-                    ilType,
-                    PropertyAttributes.None,
-                    emptyILCustomAttrs,
-                    Some(mkILMethRef (ilTypeRef, ILCallingConv.Instance, "get_" + name, 0, [], ilType)),
-                    None
-                )
-            )),
-            (name, fieldName, ilType))
+            match codegenStyle with
+            | PublicFields ->
+                (g.AddFieldGeneratedAttributes(mkILInstanceField (name, ilType, None, getFieldMemberAccess codegenStyle))),
+                [],
+                [],
+                (name, name, ilType)
+            | EncapsulatedProperties ->
+                let fieldName = name + "@"
+
+                (g.AddFieldGeneratedAttributes(mkILInstanceField (fieldName, ilType, None, getFieldMemberAccess codegenStyle))),
+                [
+                    g.AddMethodGeneratedAttributes(
+                        mkLdfldMethodDef ($"get_{name}", ILMemberAccess.Public, false, ilTy, fieldName, ilType, [])
+                    )
+                ],
+                [
+                    g.AddPropertyGeneratedAttributes(
+                        mkILNonGenericInstanceProperty (
+                            name,
+                            ilType,
+                            PropertyAttributes.None,
+                            emptyILCustomAttrs,
+                            Some(mkILMethRef (ilTypeRef, ILCallingConv.Instance, "get_" + name, 0, [], ilType)),
+                            None
+                        )
+                    )
+                ],
+                (name, fieldName, ilType))
 
     // Generate constructor with required arguments
     let ilCtorDef =
@@ -112,11 +141,73 @@ let mkLocalPrivateAttributeWithPropertyConstructors (g: TcGlobals, name: string,
         ILTypes.Empty,
         mkILMethods (
             ilCtorDef
-            :: (ilElements |> List.fold (fun acc (_, getter, _, _) -> getter :: acc) [])
+            :: (ilElements |> List.fold (fun acc (_, getter, _, _) -> getter @ acc) [])
         ),
         mkILFields (ilElements |> List.map (fun (field, _, _, _) -> field)),
         emptyILTypeDefs,
-        mkILProperties (ilElements |> List.map (fun (_, _, property, _) -> property)),
+        mkILProperties (ilElements |> List.collect (fun (_, _, props, _) -> props)),
+        emptyILEvents,
+        emptyILCustomAttrs,
+        ILTypeInit.BeforeField
+    )
+
+let mkLocalPrivateAttributeWithByteAndByteArrayConstructors (g: TcGlobals, name: string, bytePropertyName: string) =
+    let ilTypeRef = mkILTyRef (ILScopeRef.Local, name)
+    let ilTy = mkILFormalNamedTy ILBoxity.AsObject ilTypeRef []
+
+    let fieldName = bytePropertyName
+    let fieldType = g.ilg.typ_ByteArray
+
+    let fieldDef =
+        g.AddFieldGeneratedAttributes(mkILInstanceField (fieldName, fieldType, None, ILMemberAccess.Public))
+
+    // Constructor taking an array
+    let ilArrayCtorDef =
+        g.AddMethodGeneratedAttributes(
+            mkILSimpleStorageCtorWithParamNames (
+                Some g.ilg.typ_Attribute.TypeSpec,
+                ilTy,
+                [],
+                [ (fieldName, fieldName, fieldType) ],
+                ILMemberAccess.Public,
+                None,
+                None
+            )
+        )
+
+    let ilScalarCtorDef =
+        let scalarValueIlType = g.ilg.typ_Byte
+
+        g.AddMethodGeneratedAttributes(
+            let code =
+                [
+                    mkLdarg0
+                    mkNormalCall (mkILCtorMethSpecForTy (mkILBoxedType g.ilg.typ_Attribute.TypeSpec, [])) // Base class .ctor
+
+                    mkLdarg0 // Prepare 'this' to be on bottom of the stack
+                    mkLdcInt32 1
+                    I_newarr(ILArrayShape.SingleDimensional, scalarValueIlType) // new byte[1]
+                    AI_dup // Duplicate the array pointer in stack, 1 for stelem and 1 for stfld
+                    mkLdcInt32 0
+                    mkLdarg 1us
+                    I_stelem DT_I1 // array[0] = argument from .ctor
+                    mkNormalStfld (mkILFieldSpecInTy (ilTy, fieldName, fieldType))
+                ]
+
+            let body = mkMethodBody (false, [], 8, nonBranchingInstrsToCode code, None, None)
+            mkILCtor (ILMemberAccess.Public, [ mkILParamNamed ("scalarByteValue", scalarValueIlType) ], body)
+        )
+
+    mkILGenericClass (
+        name,
+        ILTypeDefAccess.Private,
+        ILGenericParameterDefs.Empty,
+        g.ilg.typ_Attribute,
+        ILTypes.Empty,
+        mkILMethods ([ ilScalarCtorDef; ilArrayCtorDef ]),
+        mkILFields [ fieldDef ],
+        emptyILTypeDefs,
+        emptyILProperties,
         emptyILEvents,
         emptyILCustomAttrs,
         ILTypeInit.BeforeField
@@ -166,13 +257,6 @@ let GetReadOnlyAttribute (g: TcGlobals) =
 let GetIsUnmanagedAttribute (g: TcGlobals) =
     getPotentiallyEmbedableAttribute g g.attrib_IsUnmanagedAttribute
 
-let GenReadOnlyAttributeIfNecessary g ty =
-    if isInByrefTy g ty then
-        let attr = GetReadOnlyAttribute g
-        Some attr
-    else
-        None
-
 let GetDynamicallyAccessedMemberTypes (g: TcGlobals) =
     let tref = g.enum_DynamicallyAccessedMemberTypes.TypeRef
 
@@ -216,7 +300,7 @@ let GetDynamicDependencyAttribute (g: TcGlobals) memberTypes (ilType: ILType) =
             let properties =
                 Some [ "MemberType", GetDynamicallyAccessedMemberTypes g; "Type", g.ilg.typ_Type ]
 
-            mkLocalPrivateAttributeWithPropertyConstructors (g, tref.Name, properties))
+            mkLocalPrivateAttributeWithPropertyConstructors (g, tref.Name, properties, EncapsulatedProperties))
     )
 
     let typIlMemberTypes =
@@ -229,6 +313,163 @@ let GetDynamicDependencyAttribute (g: TcGlobals) memberTypes (ilType: ILType) =
         []
     )
 
+/// Generates NullableContextAttribute[1], which has the meaning of:
+/// Nested items not being annotated with Nullable attribute themselves are interpreted as being withoutnull
+/// Doing it that way is a heuristical decision supporting limited usage of (| null) annotations and not allowing nulls in >50% of F# code
+/// (if majority of fields/parameters/return values would be nullable, this heuristic would lead to bloat of generated metadata)
+let GetNullableContextAttribute (g: TcGlobals) =
+    let tref = g.attrib_NullableContextAttribute.TypeRef
+
+    g.TryEmbedILType(
+        tref,
+        (fun () ->
+            let fields = Some [ "Flag", g.ilg.typ_Byte ]
+            mkLocalPrivateAttributeWithPropertyConstructors (g, tref.Name, fields, PublicFields))
+    )
+
+    mkILCustomAttribute (tref, [ g.ilg.typ_Byte ], [ ILAttribElem.Byte 1uy ], [])
+
+let GetNotNullWhenTrueAttribute (g: TcGlobals) (propNames: string array) =
+    let tref = g.attrib_MemberNotNullWhenAttribute.TypeRef
+
+    g.TryEmbedILType(
+        tref,
+        (fun () ->
+            let fields =
+                Some [ "ReturnValue", g.ilg.typ_Bool; "Members", g.ilg.typ_StringArray ]
+
+            mkLocalPrivateAttributeWithPropertyConstructors (g, tref.Name, fields, EncapsulatedProperties))
+    )
+
+    let stringArgs =
+        propNames |> Array.map (Some >> ILAttribElem.String) |> List.ofArray
+
+    mkILCustomAttribute (
+        tref,
+        [ g.ilg.typ_Bool; g.ilg.typ_StringArray ],
+        [ ILAttribElem.Bool true; ILAttribElem.Array(g.ilg.typ_String, stringArgs) ],
+        []
+    )
+
+let GetNullableAttribute (g: TcGlobals) (nullnessInfos: TypedTree.NullnessInfo list) =
+    let tref = g.attrib_NullableAttribute.TypeRef
+
+    g.TryEmbedILType(tref, (fun () -> mkLocalPrivateAttributeWithByteAndByteArrayConstructors (g, tref.Name, "NullableFlags")))
+
+    let byteValue ni =
+        match ni with
+        | NullnessInfo.WithNull -> 2uy
+        | NullnessInfo.AmbivalentToNull -> 0uy
+        | NullnessInfo.WithoutNull -> 1uy
+
+    let bytes = nullnessInfos |> List.map (fun ni -> byteValue ni |> ILAttribElem.Byte)
+
+    match bytes with
+    | [ singleByte ] -> mkILCustomAttribute (tref, [ g.ilg.typ_Byte ], [ singleByte ], [])
+    | listOfBytes -> mkILCustomAttribute (tref, [ g.ilg.typ_ByteArray ], [ ILAttribElem.Array(g.ilg.typ_Byte, listOfBytes) ], [])
+
+let GenReadOnlyIfNecessary g ty =
+    if isInByrefTy g ty then
+        let attr = GetReadOnlyAttribute g
+        Some attr
+    else
+        None
+
+(* Nullness metadata format in C#: https://github.com/dotnet/roslyn/blob/main/docs/features/nullable-metadata.md
+Each type reference in metadata may have an associated NullableAttribute with a byte[] where each byte represents nullability: 0 for oblivious, 1 for not annotated, and 2 for annotated.
+
+The byte[] is constructed as follows:
+
+Reference type: the nullability (0, 1, or 2), followed by the representation of the type arguments in order including containing types
+Nullable value type: the representation of the type argument only
+Non-generic value type: skipped
+Generic value type: 0, followed by the representation of the type arguments in order including containing types
+Array: the nullability (0, 1, or 2), followed by the representation of the element type
+Tuple: the representation of the underlying constructed type
+Type parameter reference: the nullability (0, 1, or 2, with 0 for unconstrained type parameter)
+*)
+let rec GetNullnessFromTType (g: TcGlobals) ty =
+    match ty |> stripTyEqns g with
+    | TType_app (tcref, tinst, nullness) ->
+        let isValueType = tcref.IsStructOrEnumTycon
+        let isNonGeneric = tinst.IsEmpty
+
+        if isNonGeneric && isValueType then
+            // Non-generic value type: skipped
+            []
+        else
+            [
+                if tyconRefEq g g.system_Nullable_tcref tcref then
+                    // Nullable value type: the representation of the type argument only
+                    ()
+                else if isValueType then
+                    // Generic value type: 0, followed by the representation of the type arguments in order including containing types
+                    yield NullnessInfo.AmbivalentToNull
+                else
+                    // Reference type: the nullability (0, 1, or 2), followed by the representation of the type arguments in order including containing types
+                    yield nullness.Evaluate()
+
+                for tt in tinst do
+                    yield! GetNullnessFromTType g tt
+            ]
+
+    | TType_fun (domainTy, retTy, nullness) ->
+        // FsharpFunc
+        [
+            yield nullness.Evaluate()
+            yield! GetNullnessFromTType g domainTy
+            yield! GetNullnessFromTType g retTy
+        ]
+
+    | TType_tuple (tupInfo, elementTypes) ->
+        // Tuple: the representation of the underlying constructed type
+        [
+            if evalTupInfoIsStruct tupInfo then
+                yield NullnessInfo.AmbivalentToNull
+            else
+                yield NullnessInfo.WithoutNull
+            for t in elementTypes do
+                yield! GetNullnessFromTType g t
+        ]
+
+    | TType_anon (anonInfo, tys) ->
+        // It is unlikely for an anon type to be used from C# due to the mangled name, but can still carry the nullability info about it's generic type arguments == the types of the fields
+        [
+            if evalAnonInfoIsStruct anonInfo then
+                yield NullnessInfo.AmbivalentToNull
+            else
+                yield NullnessInfo.WithoutNull
+            for t in tys do
+                yield! GetNullnessFromTType g t
+        ]
+    | TType_forall _
+    | TType_ucase _
+    | TType_var _
+    | TType_measure _ -> []
+
+let GenNullnessIfNecessary (g: TcGlobals) ty =
+    if g.langFeatureNullness && g.checkNullness then
+        let nullnessList = GetNullnessFromTType g ty
+
+        match nullnessList with
+        // Optimizations as done in C# :: If the byte[] is empty, the NullableAttribute is omitted.
+        | [] -> None
+        // Optimizations as done in C# :: If all values in the byte[] are the same, the NullableAttribute is constructed with that single byte value.
+        | head :: tail when tail |> List.forall ((=) head) ->
+            match head with
+            // For F# code, each type has an automatically generated NullableContextAttribute(1)
+            // That means an implicit (hidden, not generated) Nullable(1) attribute
+            | NullnessInfo.WithoutNull -> None
+            | _ -> GetNullableAttribute g [ head ] |> Some
+        | nonUniformList -> GetNullableAttribute g nonUniformList |> Some
+    else
+        None
+
+let GenAdditionalAttributesForTy g ty =
+    let readOnly = GenReadOnlyIfNecessary g ty |> Option.toList
+    let nullable = GenNullnessIfNecessary g ty |> Option.toList
+    readOnly @ nullable
+
 /// Generate "modreq([mscorlib]System.Runtime.InteropServices.InAttribute)" on inref types.
 let GenReadOnlyModReqIfNecessary (g: TcGlobals) ty ilTy =
     let add = isInByrefTy g ty && g.attrib_InAttribute.TyconRef.CanDeref
diff --git a/src/Compiler/CodeGen/IlxGenSupport.fsi b/src/Compiler/CodeGen/IlxGenSupport.fsi
index 24968a25ec6..6bd3723e886 100644
--- a/src/Compiler/CodeGen/IlxGenSupport.fsi
+++ b/src/Compiler/CodeGen/IlxGenSupport.fsi
@@ -19,6 +19,9 @@ val mkLdfldMethodDef:
 
 val GetDynamicDependencyAttribute: g: TcGlobals -> memberTypes: int32 -> ilType: ILType -> ILAttribute
 val GenReadOnlyModReqIfNecessary: g: TcGlobals -> ty: TypedTree.TType -> ilTy: ILType -> ILType
-val GenReadOnlyAttributeIfNecessary: g: TcGlobals -> ty: TypedTree.TType -> ILAttribute option
+val GenAdditionalAttributesForTy: g: TcGlobals -> ty: TypedTree.TType -> ILAttribute list
 val GetReadOnlyAttribute: g: TcGlobals -> ILAttribute
 val GetIsUnmanagedAttribute: g: TcGlobals -> ILAttribute
+val GetNullableAttribute: g: TcGlobals -> nullnessInfos: TypedTree.NullnessInfo list -> ILAttribute
+val GetNullableContextAttribute: g: TcGlobals -> ILAttribute
+val GetNotNullWhenTrueAttribute: g: TcGlobals -> string array -> ILAttribute
diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs
index d8a0084db96..9b09c35053b 100755
--- a/src/Compiler/TypedTree/TcGlobals.fs
+++ b/src/Compiler/TypedTree/TcGlobals.fs
@@ -347,6 +347,9 @@ type TcGlobals(
       match name with
       | "System.Runtime.CompilerServices.IsReadOnlyAttribute"
       | "System.Runtime.CompilerServices.IsUnmanagedAttribute"
+      | "System.Runtime.CompilerServices.NullableAttribute"
+      | "System.Runtime.CompilerServices.NullableContextAttribute"
+      | "System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute"
       | "System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute"
       | "System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes" -> true
       | _ -> false
@@ -1448,6 +1451,9 @@ type TcGlobals(
   member val attrib_IsReadOnlyAttribute = findOrEmbedSysPublicType "System.Runtime.CompilerServices.IsReadOnlyAttribute"
   member val attrib_IsUnmanagedAttribute = findOrEmbedSysPublicType "System.Runtime.CompilerServices.IsUnmanagedAttribute"
   member val attrib_DynamicDependencyAttribute = findOrEmbedSysPublicType "System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute"
+  member val attrib_NullableAttribute = findOrEmbedSysPublicType "System.Runtime.CompilerServices.NullableAttribute"
+  member val attrib_NullableContextAttribute = findOrEmbedSysPublicType "System.Runtime.CompilerServices.NullableContextAttribute"
+  member val attrib_MemberNotNullWhenAttribute  = findOrEmbedSysPublicType "System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute"
   member val enum_DynamicallyAccessedMemberTypes = findOrEmbedSysPublicType "System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes"
 
   member val attrib_SystemObsolete = findSysAttrib "System.ObsoleteAttribute"
diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs
index 73632fbd66c..a2d82383aa9 100644
--- a/src/Compiler/TypedTree/TypedTreeOps.fs
+++ b/src/Compiler/TypedTree/TypedTreeOps.fs
@@ -3487,6 +3487,9 @@ let TryFindILAttributeOpt attr attrs =
     | Some (AttribInfo (atref, _)) -> HasILAttribute atref attrs
     | _ -> false
 
+let IsILAttrib  (AttribInfo (builtInAttrRef, _)) attr = isILAttrib builtInAttrRef attr
+    
+
 /// Analyze three cases for attributes declared on type definitions: IL-declared attributes, F#-declared attributes and
 /// provided attributes.
 //
diff --git a/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi
index 608c242e942..2403a8ad4ef 100755
--- a/src/Compiler/TypedTree/TypedTreeOps.fsi
+++ b/src/Compiler/TypedTree/TypedTreeOps.fsi
@@ -2238,6 +2238,8 @@ val mkLdelem: TcGlobals -> range -> TType -> Expr -> Expr -> Expr
 
 val TryDecodeILAttribute: ILTypeRef -> ILAttributes -> (ILAttribElem list * ILAttributeNamedArg list) option
 
+val IsILAttrib: BuiltinAttribInfo -> ILAttribute -> bool
+
 val TryFindILAttribute: BuiltinAttribInfo -> ILAttributes -> bool
 
 val TryFindILAttributeOpt: BuiltinAttribInfo option -> ILAttributes -> bool
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs
new file mode 100644
index 00000000000..1178f3e704e
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs
@@ -0,0 +1,14 @@
+module MyTestModule
+
+let justInt = 42
+let maybeString : string | null = null
+let maybeListOfMaybeString : List<_> | null = [maybeString]
+
+let giveMeA () =
+    {| A = maybeString; B = maybeListOfMaybeString; C = justInt|}
+
+let giveMeB () =
+    {| A = justInt; B = justInt; C = justInt|}
+
+let giveMeC () =
+    {| A = maybeString; B = maybeString; C = maybeString|}
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.net472.bsl
new file mode 100644
index 00000000000..cfed4707176
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.net472.bsl
@@ -0,0 +1,846 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .method public specialname static int32 
+          get_justInt() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldc.i4.s   42
+    IL_0002:  ret
+  } 
+
+  .method public specialname static string 
+          get_maybeString() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldnull
+    IL_0001:  ret
+  } 
+
+  .method public specialname static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 
+          get_maybeListOfMaybeString() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldsfld     class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$MyTestModule::maybeListOfMaybeString@5
+    IL_0005:  ret
+  } 
+
+  .method public static class '<>f__AnonymousType2430756162`3',int32> 
+          giveMeA() cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 04 00 00 00 01 02 02 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  call       string MyTestModule::get_maybeString()
+    IL_0005:  call       class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 MyTestModule::get_maybeListOfMaybeString()
+    IL_000a:  call       int32 MyTestModule::get_justInt()
+    IL_000f:  newobj     instance void class '<>f__AnonymousType2430756162`3',int32>::.ctor(!0,
+                                                                                                                                                                        !1,
+                                                                                                                                                                        !2)
+    IL_0014:  ret
+  } 
+
+  .method public static class '<>f__AnonymousType2430756162`3' 
+          giveMeB() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  call       int32 MyTestModule::get_justInt()
+    IL_0005:  call       int32 MyTestModule::get_justInt()
+    IL_000a:  call       int32 MyTestModule::get_justInt()
+    IL_000f:  newobj     instance void class '<>f__AnonymousType2430756162`3'::.ctor(!0,
+                                                                                                        !1,
+                                                                                                        !2)
+    IL_0014:  ret
+  } 
+
+  .method public static class '<>f__AnonymousType2430756162`3' 
+          giveMeC() cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 04 00 00 00 01 02 02 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  call       string MyTestModule::get_maybeString()
+    IL_0005:  call       string MyTestModule::get_maybeString()
+    IL_000a:  call       string MyTestModule::get_maybeString()
+    IL_000f:  newobj     instance void class '<>f__AnonymousType2430756162`3'::.ctor(!0,
+                                                                                                           !1,
+                                                                                                           !2)
+    IL_0014:  ret
+  } 
+
+  .property int32 justInt()
+  {
+    .get int32 MyTestModule::get_justInt()
+  } 
+  .property string maybeString()
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .get string MyTestModule::get_maybeString()
+  } 
+  .property class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1
+          maybeListOfMaybeString()
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) 
+    .get class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 MyTestModule::get_maybeListOfMaybeString()
+  } 
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .field static assembly initonly class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 maybeListOfMaybeString@5
+  .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .field static assembly int32 init@
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method private specialname rtspecialname static 
+          void  .cctor() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  call       string MyTestModule::get_maybeString()
+    IL_0005:  call       class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty()
+    IL_000a:  call       class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0,
+                                                                                                                                                                     class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1)
+    IL_000f:  stsfld     class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$MyTestModule::maybeListOfMaybeString@5
+    IL_0014:  ret
+  } 
+
+} 
+
+.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType2430756162`3'<'j__TPar','j__TPar','j__TPar'>
+       extends [runtime]System.Object
+       implements [runtime]System.Collections.IStructuralComparable,
+                  [runtime]System.IComparable,
+                  class [runtime]System.IComparable`1f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>>,
+                  [runtime]System.Collections.IStructuralEquatable,
+                  class [runtime]System.IEquatable`1f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>>
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .field private !'j__TPar' A@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .field private !'j__TPar' B@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .field private !'j__TPar' C@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(!'j__TPar' A,
+                               !'j__TPar' B,
+                               !'j__TPar' C) cil managed
+  {
+    .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                            class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E   
+                                                                                                                             79 6D 6F 75 73 54 79 70 65 32 34 33 30 37 35 36   
+                                                                                                                             31 36 32 60 33 00 00 )                            
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Object::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_000d:  ldarg.0
+    IL_000e:  ldarg.2
+    IL_000f:  stfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_0014:  ldarg.0
+    IL_0015:  ldarg.3
+    IL_0016:  stfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_001b:  ret
+  } 
+
+  .method public hidebysig specialname instance !'j__TPar' 
+          get_A() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_0006:  ret
+  } 
+
+  .method public hidebysig specialname instance !'j__TPar' 
+          get_B() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_0006:  ret
+  } 
+
+  .method public hidebysig specialname instance !'j__TPar' 
+          get_C() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_0006:  ret
+  } 
+
+  .method public strict virtual instance string 
+          ToString() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldstr      "%+A"
+    IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>>::.ctor(string)
+    IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+    IL_000f:  ldarg.0
+    IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>,string>::Invoke(!0)
+    IL_0015:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance int32  CompareTo(class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'> obj) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  5
+    .locals init (int32 V_0,
+             int32 V_1)
+    IL_0000:  ldarg.0
+    IL_0001:  brfalse.s  IL_0067
+
+    IL_0003:  ldarg.1
+    IL_0004:  brfalse.s  IL_0065
+
+    IL_0006:  call       class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer()
+    IL_000b:  ldarg.0
+    IL_000c:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_0011:  ldarg.1
+    IL_0012:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_0017:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer,
+                                                                                                                                   !!0,
+                                                                                                                                   !!0)
+    IL_001c:  stloc.0
+    IL_001d:  ldloc.0
+    IL_001e:  ldc.i4.0
+    IL_001f:  bge.s      IL_0023
+
+    IL_0021:  ldloc.0
+    IL_0022:  ret
+
+    IL_0023:  ldloc.0
+    IL_0024:  ldc.i4.0
+    IL_0025:  ble.s      IL_0029
+
+    IL_0027:  ldloc.0
+    IL_0028:  ret
+
+    IL_0029:  call       class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer()
+    IL_002e:  ldarg.0
+    IL_002f:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_0034:  ldarg.1
+    IL_0035:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_003a:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer,
+                                                                                                                                   !!0,
+                                                                                                                                   !!0)
+    IL_003f:  stloc.1
+    IL_0040:  ldloc.1
+    IL_0041:  ldc.i4.0
+    IL_0042:  bge.s      IL_0046
+
+    IL_0044:  ldloc.1
+    IL_0045:  ret
+
+    IL_0046:  ldloc.1
+    IL_0047:  ldc.i4.0
+    IL_0048:  ble.s      IL_004c
+
+    IL_004a:  ldloc.1
+    IL_004b:  ret
+
+    IL_004c:  call       class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer()
+    IL_0051:  ldarg.0
+    IL_0052:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_0057:  ldarg.1
+    IL_0058:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_005d:  tail.
+    IL_005f:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer,
+                                                                                                                                   !!0,
+                                                                                                                                   !!0)
+    IL_0064:  ret
+
+    IL_0065:  ldc.i4.1
+    IL_0066:  ret
+
+    IL_0067:  ldarg.1
+    IL_0068:  brfalse.s  IL_006c
+
+    IL_006a:  ldc.i4.m1
+    IL_006b:  ret
+
+    IL_006c:  ldc.i4.0
+    IL_006d:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance int32  CompareTo(object obj) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldarg.1
+    IL_0002:  unbox.any  class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>
+    IL_0007:  tail.
+    IL_0009:  callvirt   instance int32 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType2430756162`3')
+    IL_000e:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance int32  CompareTo(object obj,
+                                    class [runtime]System.Collections.IComparer comp) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  5
+    .locals init (class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'> V_0,
+             class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'> V_1,
+             int32 V_2,
+             int32 V_3)
+    IL_0000:  ldarg.1
+    IL_0001:  unbox.any  class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>
+    IL_0006:  stloc.0
+    IL_0007:  ldloc.0
+    IL_0008:  stloc.1
+    IL_0009:  ldarg.0
+    IL_000a:  brfalse.s  IL_0069
+
+    IL_000c:  ldarg.1
+    IL_000d:  unbox.any  class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>
+    IL_0012:  brfalse.s  IL_0067
+
+    IL_0014:  ldarg.2
+    IL_0015:  ldarg.0
+    IL_0016:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_001b:  ldloc.1
+    IL_001c:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_0021:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer,
+                                                                                                                                   !!0,
+                                                                                                                                   !!0)
+    IL_0026:  stloc.2
+    IL_0027:  ldloc.2
+    IL_0028:  ldc.i4.0
+    IL_0029:  bge.s      IL_002d
+
+    IL_002b:  ldloc.2
+    IL_002c:  ret
+
+    IL_002d:  ldloc.2
+    IL_002e:  ldc.i4.0
+    IL_002f:  ble.s      IL_0033
+
+    IL_0031:  ldloc.2
+    IL_0032:  ret
+
+    IL_0033:  ldarg.2
+    IL_0034:  ldarg.0
+    IL_0035:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_003a:  ldloc.1
+    IL_003b:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_0040:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer,
+                                                                                                                                   !!0,
+                                                                                                                                   !!0)
+    IL_0045:  stloc.3
+    IL_0046:  ldloc.3
+    IL_0047:  ldc.i4.0
+    IL_0048:  bge.s      IL_004c
+
+    IL_004a:  ldloc.3
+    IL_004b:  ret
+
+    IL_004c:  ldloc.3
+    IL_004d:  ldc.i4.0
+    IL_004e:  ble.s      IL_0052
+
+    IL_0050:  ldloc.3
+    IL_0051:  ret
+
+    IL_0052:  ldarg.2
+    IL_0053:  ldarg.0
+    IL_0054:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_0059:  ldloc.1
+    IL_005a:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_005f:  tail.
+    IL_0061:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer,
+                                                                                                                                   !!0,
+                                                                                                                                   !!0)
+    IL_0066:  ret
+
+    IL_0067:  ldc.i4.1
+    IL_0068:  ret
+
+    IL_0069:  ldarg.1
+    IL_006a:  unbox.any  class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>
+    IL_006f:  brfalse.s  IL_0073
+
+    IL_0071:  ldc.i4.m1
+    IL_0072:  ret
+
+    IL_0073:  ldc.i4.0
+    IL_0074:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance int32  GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  7
+    .locals init (int32 V_0)
+    IL_0000:  ldarg.0
+    IL_0001:  brfalse.s  IL_0058
+
+    IL_0003:  ldc.i4.0
+    IL_0004:  stloc.0
+    IL_0005:  ldc.i4     0x9e3779b9
+    IL_000a:  ldarg.1
+    IL_000b:  ldarg.0
+    IL_000c:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_0011:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer,
+                                                                                                                             !!0)
+    IL_0016:  ldloc.0
+    IL_0017:  ldc.i4.6
+    IL_0018:  shl
+    IL_0019:  ldloc.0
+    IL_001a:  ldc.i4.2
+    IL_001b:  shr
+    IL_001c:  add
+    IL_001d:  add
+    IL_001e:  add
+    IL_001f:  stloc.0
+    IL_0020:  ldc.i4     0x9e3779b9
+    IL_0025:  ldarg.1
+    IL_0026:  ldarg.0
+    IL_0027:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_002c:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer,
+                                                                                                                             !!0)
+    IL_0031:  ldloc.0
+    IL_0032:  ldc.i4.6
+    IL_0033:  shl
+    IL_0034:  ldloc.0
+    IL_0035:  ldc.i4.2
+    IL_0036:  shr
+    IL_0037:  add
+    IL_0038:  add
+    IL_0039:  add
+    IL_003a:  stloc.0
+    IL_003b:  ldc.i4     0x9e3779b9
+    IL_0040:  ldarg.1
+    IL_0041:  ldarg.0
+    IL_0042:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_0047:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer,
+                                                                                                                             !!0)
+    IL_004c:  ldloc.0
+    IL_004d:  ldc.i4.6
+    IL_004e:  shl
+    IL_004f:  ldloc.0
+    IL_0050:  ldc.i4.2
+    IL_0051:  shr
+    IL_0052:  add
+    IL_0053:  add
+    IL_0054:  add
+    IL_0055:  stloc.0
+    IL_0056:  ldloc.0
+    IL_0057:  ret
+
+    IL_0058:  ldc.i4.0
+    IL_0059:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance int32  GetHashCode() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer()
+    IL_0006:  tail.
+    IL_0008:  callvirt   instance int32 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer)
+    IL_000d:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance bool  Equals(object obj,
+                                class [runtime]System.Collections.IEqualityComparer comp) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  5
+    .locals init (class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'> V_0,
+             class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'> V_1)
+    IL_0000:  ldarg.0
+    IL_0001:  brfalse.s  IL_0052
+
+    IL_0003:  ldarg.1
+    IL_0004:  isinst     class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>
+    IL_0009:  stloc.0
+    IL_000a:  ldloc.0
+    IL_000b:  brfalse.s  IL_0050
+
+    IL_000d:  ldloc.0
+    IL_000e:  stloc.1
+    IL_000f:  ldarg.2
+    IL_0010:  ldarg.0
+    IL_0011:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_0016:  ldloc.1
+    IL_0017:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_001c:  call       bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer,
+                                                                                                                                !!0,
+                                                                                                                                !!0)
+    IL_0021:  brfalse.s  IL_004e
+
+    IL_0023:  ldarg.2
+    IL_0024:  ldarg.0
+    IL_0025:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_002a:  ldloc.1
+    IL_002b:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_0030:  call       bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer,
+                                                                                                                                !!0,
+                                                                                                                                !!0)
+    IL_0035:  brfalse.s  IL_004c
+
+    IL_0037:  ldarg.2
+    IL_0038:  ldarg.0
+    IL_0039:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_003e:  ldloc.1
+    IL_003f:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_0044:  tail.
+    IL_0046:  call       bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer,
+                                                                                                                                !!0,
+                                                                                                                                !!0)
+    IL_004b:  ret
+
+    IL_004c:  ldc.i4.0
+    IL_004d:  ret
+
+    IL_004e:  ldc.i4.0
+    IL_004f:  ret
+
+    IL_0050:  ldc.i4.0
+    IL_0051:  ret
+
+    IL_0052:  ldarg.1
+    IL_0053:  ldnull
+    IL_0054:  cgt.un
+    IL_0056:  ldc.i4.0
+    IL_0057:  ceq
+    IL_0059:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance bool  Equals(class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'> obj) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  4
+    IL_0000:  ldarg.0
+    IL_0001:  brfalse.s  IL_0046
+
+    IL_0003:  ldarg.1
+    IL_0004:  brfalse.s  IL_0044
+
+    IL_0006:  ldarg.0
+    IL_0007:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_000c:  ldarg.1
+    IL_000d:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_0012:  call       bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0,
+                                                                                                                      !!0)
+    IL_0017:  brfalse.s  IL_0042
+
+    IL_0019:  ldarg.0
+    IL_001a:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_001f:  ldarg.1
+    IL_0020:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_0025:  call       bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0,
+                                                                                                                      !!0)
+    IL_002a:  brfalse.s  IL_0040
+
+    IL_002c:  ldarg.0
+    IL_002d:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_0032:  ldarg.1
+    IL_0033:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_0038:  tail.
+    IL_003a:  call       bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0,
+                                                                                                                      !!0)
+    IL_003f:  ret
+
+    IL_0040:  ldc.i4.0
+    IL_0041:  ret
+
+    IL_0042:  ldc.i4.0
+    IL_0043:  ret
+
+    IL_0044:  ldc.i4.0
+    IL_0045:  ret
+
+    IL_0046:  ldarg.1
+    IL_0047:  ldnull
+    IL_0048:  cgt.un
+    IL_004a:  ldc.i4.0
+    IL_004b:  ceq
+    IL_004d:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance bool  Equals(object obj) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  4
+    .locals init (class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'> V_0)
+    IL_0000:  ldarg.1
+    IL_0001:  isinst     class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>
+    IL_0006:  stloc.0
+    IL_0007:  ldloc.0
+    IL_0008:  brfalse.s  IL_0014
+
+    IL_000a:  ldarg.0
+    IL_000b:  ldloc.0
+    IL_000c:  tail.
+    IL_000e:  callvirt   instance bool class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType2430756162`3')
+    IL_0013:  ret
+
+    IL_0014:  ldc.i4.0
+    IL_0015:  ret
+  } 
+
+  .property instance !'j__TPar' A()
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) 
+    .get instance !'j__TPar' '<>f__AnonymousType2430756162`3'::get_A()
+  } 
+  .property instance !'j__TPar' B()
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) 
+    .get instance !'j__TPar' '<>f__AnonymousType2430756162`3'::get_B()
+  } 
+  .property instance !'j__TPar' C()
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) 
+    .get instance !'j__TPar' '<>f__AnonymousType2430756162`3'::get_C()
+  } 
+} 
+
+.class private auto ansi serializable sealed System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes
+       extends [runtime]System.Enum
+{
+  .custom instance void [runtime]System.FlagsAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public specialname rtspecialname int32 value__
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes All = int32(0xFFFFFFFF)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes None = int32(0x00000000)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicParameterlessConstructor = int32(0x00000001)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicConstructors = int32(0x00000003)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicConstructors = int32(0x00000004)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicMethods = int32(0x00000008)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicMethods = int32(0x00000010)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicFields = int32(0x00000020)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicFields = int32(0x00000040)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicNestedTypes = int32(0x00000080)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicNestedTypes = int32(0x00000100)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicProperties = int32(0x00000200)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicProperties = int32(0x00000400)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicEvents = int32(0x00000800)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicEvents = int32(0x00001000)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes Interfaces = int32(0x00002000)
+} 
+
+.class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute
+       extends [runtime]System.Attribute
+{
+  .field private valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field private class [runtime]System.Type Type@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType,
+                               class [runtime]System.Type Type) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::MemberType@
+    IL_000d:  ldarg.0
+    IL_000e:  ldarg.2
+    IL_000f:  stfld      class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::Type@
+    IL_0014:  ret
+  } 
+
+  .method public hidebysig specialname instance class [runtime]System.Type 
+          get_Type() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::Type@
+    IL_0006:  ret
+  } 
+
+  .method public hidebysig specialname instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes 
+          get_MemberType() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::MemberType@
+    IL_0006:  ret
+  } 
+
+  .property instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes
+          MemberType()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::get_MemberType()
+  } 
+  .property instance class [runtime]System.Type
+          Type()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::get_Type()
+  } 
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.netcore.bsl
new file mode 100644
index 00000000000..1f5eb583c76
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.netcore.bsl
@@ -0,0 +1,753 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .method public specialname static int32 
+          get_justInt() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldc.i4.s   42
+    IL_0002:  ret
+  } 
+
+  .method public specialname static string 
+          get_maybeString() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldnull
+    IL_0001:  ret
+  } 
+
+  .method public specialname static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 
+          get_maybeListOfMaybeString() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldsfld     class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$MyTestModule::maybeListOfMaybeString@5
+    IL_0005:  ret
+  } 
+
+  .method public static class '<>f__AnonymousType2430756162`3',int32> 
+          giveMeA() cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 04 00 00 00 01 02 02 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  call       string MyTestModule::get_maybeString()
+    IL_0005:  call       class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 MyTestModule::get_maybeListOfMaybeString()
+    IL_000a:  call       int32 MyTestModule::get_justInt()
+    IL_000f:  newobj     instance void class '<>f__AnonymousType2430756162`3',int32>::.ctor(!0,
+                                                                                                                                                                        !1,
+                                                                                                                                                                        !2)
+    IL_0014:  ret
+  } 
+
+  .method public static class '<>f__AnonymousType2430756162`3' 
+          giveMeB() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  call       int32 MyTestModule::get_justInt()
+    IL_0005:  call       int32 MyTestModule::get_justInt()
+    IL_000a:  call       int32 MyTestModule::get_justInt()
+    IL_000f:  newobj     instance void class '<>f__AnonymousType2430756162`3'::.ctor(!0,
+                                                                                                        !1,
+                                                                                                        !2)
+    IL_0014:  ret
+  } 
+
+  .method public static class '<>f__AnonymousType2430756162`3' 
+          giveMeC() cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 04 00 00 00 01 02 02 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  call       string MyTestModule::get_maybeString()
+    IL_0005:  call       string MyTestModule::get_maybeString()
+    IL_000a:  call       string MyTestModule::get_maybeString()
+    IL_000f:  newobj     instance void class '<>f__AnonymousType2430756162`3'::.ctor(!0,
+                                                                                                           !1,
+                                                                                                           !2)
+    IL_0014:  ret
+  } 
+
+  .property int32 justInt()
+  {
+    .get int32 MyTestModule::get_justInt()
+  } 
+  .property string maybeString()
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .get string MyTestModule::get_maybeString()
+  } 
+  .property class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1
+          maybeListOfMaybeString()
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) 
+    .get class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 MyTestModule::get_maybeListOfMaybeString()
+  } 
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .field static assembly initonly class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 maybeListOfMaybeString@5
+  .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .field static assembly int32 init@
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method private specialname rtspecialname static 
+          void  .cctor() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  call       string MyTestModule::get_maybeString()
+    IL_0005:  call       class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty()
+    IL_000a:  call       class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0,
+                                                                                                                                                                     class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1)
+    IL_000f:  stsfld     class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$MyTestModule::maybeListOfMaybeString@5
+    IL_0014:  ret
+  } 
+
+} 
+
+.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType2430756162`3'<'j__TPar','j__TPar','j__TPar'>
+       extends [runtime]System.Object
+       implements [runtime]System.Collections.IStructuralComparable,
+                  [runtime]System.IComparable,
+                  class [runtime]System.IComparable`1f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>>,
+                  [runtime]System.Collections.IStructuralEquatable,
+                  class [runtime]System.IEquatable`1f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>>
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .field private !'j__TPar' A@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .field private !'j__TPar' B@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .field private !'j__TPar' C@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(!'j__TPar' A,
+                               !'j__TPar' B,
+                               !'j__TPar' C) cil managed
+  {
+    .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                            class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E   
+                                                                                                                                                   79 6D 6F 75 73 54 79 70 65 32 34 33 30 37 35 36   
+                                                                                                                                                   31 36 32 60 33 00 00 )                            
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Object::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_000d:  ldarg.0
+    IL_000e:  ldarg.2
+    IL_000f:  stfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_0014:  ldarg.0
+    IL_0015:  ldarg.3
+    IL_0016:  stfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_001b:  ret
+  } 
+
+  .method public hidebysig specialname instance !'j__TPar' 
+          get_A() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_0006:  ret
+  } 
+
+  .method public hidebysig specialname instance !'j__TPar' 
+          get_B() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_0006:  ret
+  } 
+
+  .method public hidebysig specialname instance !'j__TPar' 
+          get_C() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_0006:  ret
+  } 
+
+  .method public strict virtual instance string 
+          ToString() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldstr      "%+A"
+    IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>>::.ctor(string)
+    IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+    IL_000f:  ldarg.0
+    IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>,string>::Invoke(!0)
+    IL_0015:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance int32  CompareTo(class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'> obj) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  5
+    .locals init (int32 V_0,
+             int32 V_1)
+    IL_0000:  ldarg.0
+    IL_0001:  brfalse.s  IL_0067
+
+    IL_0003:  ldarg.1
+    IL_0004:  brfalse.s  IL_0065
+
+    IL_0006:  call       class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer()
+    IL_000b:  ldarg.0
+    IL_000c:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_0011:  ldarg.1
+    IL_0012:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_0017:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer,
+                                                                                                                                   !!0,
+                                                                                                                                   !!0)
+    IL_001c:  stloc.0
+    IL_001d:  ldloc.0
+    IL_001e:  ldc.i4.0
+    IL_001f:  bge.s      IL_0023
+
+    IL_0021:  ldloc.0
+    IL_0022:  ret
+
+    IL_0023:  ldloc.0
+    IL_0024:  ldc.i4.0
+    IL_0025:  ble.s      IL_0029
+
+    IL_0027:  ldloc.0
+    IL_0028:  ret
+
+    IL_0029:  call       class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer()
+    IL_002e:  ldarg.0
+    IL_002f:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_0034:  ldarg.1
+    IL_0035:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_003a:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer,
+                                                                                                                                   !!0,
+                                                                                                                                   !!0)
+    IL_003f:  stloc.1
+    IL_0040:  ldloc.1
+    IL_0041:  ldc.i4.0
+    IL_0042:  bge.s      IL_0046
+
+    IL_0044:  ldloc.1
+    IL_0045:  ret
+
+    IL_0046:  ldloc.1
+    IL_0047:  ldc.i4.0
+    IL_0048:  ble.s      IL_004c
+
+    IL_004a:  ldloc.1
+    IL_004b:  ret
+
+    IL_004c:  call       class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer()
+    IL_0051:  ldarg.0
+    IL_0052:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_0057:  ldarg.1
+    IL_0058:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_005d:  tail.
+    IL_005f:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer,
+                                                                                                                                   !!0,
+                                                                                                                                   !!0)
+    IL_0064:  ret
+
+    IL_0065:  ldc.i4.1
+    IL_0066:  ret
+
+    IL_0067:  ldarg.1
+    IL_0068:  brfalse.s  IL_006c
+
+    IL_006a:  ldc.i4.m1
+    IL_006b:  ret
+
+    IL_006c:  ldc.i4.0
+    IL_006d:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance int32  CompareTo(object obj) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldarg.1
+    IL_0002:  unbox.any  class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>
+    IL_0007:  tail.
+    IL_0009:  callvirt   instance int32 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType2430756162`3')
+    IL_000e:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance int32  CompareTo(object obj,
+                                    class [runtime]System.Collections.IComparer comp) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  5
+    .locals init (class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'> V_0,
+             class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'> V_1,
+             int32 V_2,
+             int32 V_3)
+    IL_0000:  ldarg.1
+    IL_0001:  unbox.any  class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>
+    IL_0006:  stloc.0
+    IL_0007:  ldloc.0
+    IL_0008:  stloc.1
+    IL_0009:  ldarg.0
+    IL_000a:  brfalse.s  IL_0069
+
+    IL_000c:  ldarg.1
+    IL_000d:  unbox.any  class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>
+    IL_0012:  brfalse.s  IL_0067
+
+    IL_0014:  ldarg.2
+    IL_0015:  ldarg.0
+    IL_0016:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_001b:  ldloc.1
+    IL_001c:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_0021:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer,
+                                                                                                                                   !!0,
+                                                                                                                                   !!0)
+    IL_0026:  stloc.2
+    IL_0027:  ldloc.2
+    IL_0028:  ldc.i4.0
+    IL_0029:  bge.s      IL_002d
+
+    IL_002b:  ldloc.2
+    IL_002c:  ret
+
+    IL_002d:  ldloc.2
+    IL_002e:  ldc.i4.0
+    IL_002f:  ble.s      IL_0033
+
+    IL_0031:  ldloc.2
+    IL_0032:  ret
+
+    IL_0033:  ldarg.2
+    IL_0034:  ldarg.0
+    IL_0035:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_003a:  ldloc.1
+    IL_003b:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_0040:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer,
+                                                                                                                                   !!0,
+                                                                                                                                   !!0)
+    IL_0045:  stloc.3
+    IL_0046:  ldloc.3
+    IL_0047:  ldc.i4.0
+    IL_0048:  bge.s      IL_004c
+
+    IL_004a:  ldloc.3
+    IL_004b:  ret
+
+    IL_004c:  ldloc.3
+    IL_004d:  ldc.i4.0
+    IL_004e:  ble.s      IL_0052
+
+    IL_0050:  ldloc.3
+    IL_0051:  ret
+
+    IL_0052:  ldarg.2
+    IL_0053:  ldarg.0
+    IL_0054:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_0059:  ldloc.1
+    IL_005a:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_005f:  tail.
+    IL_0061:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer,
+                                                                                                                                   !!0,
+                                                                                                                                   !!0)
+    IL_0066:  ret
+
+    IL_0067:  ldc.i4.1
+    IL_0068:  ret
+
+    IL_0069:  ldarg.1
+    IL_006a:  unbox.any  class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>
+    IL_006f:  brfalse.s  IL_0073
+
+    IL_0071:  ldc.i4.m1
+    IL_0072:  ret
+
+    IL_0073:  ldc.i4.0
+    IL_0074:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance int32  GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  7
+    .locals init (int32 V_0)
+    IL_0000:  ldarg.0
+    IL_0001:  brfalse.s  IL_0058
+
+    IL_0003:  ldc.i4.0
+    IL_0004:  stloc.0
+    IL_0005:  ldc.i4     0x9e3779b9
+    IL_000a:  ldarg.1
+    IL_000b:  ldarg.0
+    IL_000c:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_0011:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer,
+                                                                                                                             !!0)
+    IL_0016:  ldloc.0
+    IL_0017:  ldc.i4.6
+    IL_0018:  shl
+    IL_0019:  ldloc.0
+    IL_001a:  ldc.i4.2
+    IL_001b:  shr
+    IL_001c:  add
+    IL_001d:  add
+    IL_001e:  add
+    IL_001f:  stloc.0
+    IL_0020:  ldc.i4     0x9e3779b9
+    IL_0025:  ldarg.1
+    IL_0026:  ldarg.0
+    IL_0027:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_002c:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer,
+                                                                                                                             !!0)
+    IL_0031:  ldloc.0
+    IL_0032:  ldc.i4.6
+    IL_0033:  shl
+    IL_0034:  ldloc.0
+    IL_0035:  ldc.i4.2
+    IL_0036:  shr
+    IL_0037:  add
+    IL_0038:  add
+    IL_0039:  add
+    IL_003a:  stloc.0
+    IL_003b:  ldc.i4     0x9e3779b9
+    IL_0040:  ldarg.1
+    IL_0041:  ldarg.0
+    IL_0042:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_0047:  call       int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer,
+                                                                                                                             !!0)
+    IL_004c:  ldloc.0
+    IL_004d:  ldc.i4.6
+    IL_004e:  shl
+    IL_004f:  ldloc.0
+    IL_0050:  ldc.i4.2
+    IL_0051:  shr
+    IL_0052:  add
+    IL_0053:  add
+    IL_0054:  add
+    IL_0055:  stloc.0
+    IL_0056:  ldloc.0
+    IL_0057:  ret
+
+    IL_0058:  ldc.i4.0
+    IL_0059:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance int32  GetHashCode() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer()
+    IL_0006:  tail.
+    IL_0008:  callvirt   instance int32 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer)
+    IL_000d:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance bool  Equals(object obj,
+                                class [runtime]System.Collections.IEqualityComparer comp) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  5
+    .locals init (class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'> V_0,
+             class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'> V_1)
+    IL_0000:  ldarg.0
+    IL_0001:  brfalse.s  IL_0052
+
+    IL_0003:  ldarg.1
+    IL_0004:  isinst     class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>
+    IL_0009:  stloc.0
+    IL_000a:  ldloc.0
+    IL_000b:  brfalse.s  IL_0050
+
+    IL_000d:  ldloc.0
+    IL_000e:  stloc.1
+    IL_000f:  ldarg.2
+    IL_0010:  ldarg.0
+    IL_0011:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_0016:  ldloc.1
+    IL_0017:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_001c:  call       bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer,
+                                                                                                                                !!0,
+                                                                                                                                !!0)
+    IL_0021:  brfalse.s  IL_004e
+
+    IL_0023:  ldarg.2
+    IL_0024:  ldarg.0
+    IL_0025:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_002a:  ldloc.1
+    IL_002b:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_0030:  call       bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer,
+                                                                                                                                !!0,
+                                                                                                                                !!0)
+    IL_0035:  brfalse.s  IL_004c
+
+    IL_0037:  ldarg.2
+    IL_0038:  ldarg.0
+    IL_0039:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_003e:  ldloc.1
+    IL_003f:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_0044:  tail.
+    IL_0046:  call       bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer,
+                                                                                                                                !!0,
+                                                                                                                                !!0)
+    IL_004b:  ret
+
+    IL_004c:  ldc.i4.0
+    IL_004d:  ret
+
+    IL_004e:  ldc.i4.0
+    IL_004f:  ret
+
+    IL_0050:  ldc.i4.0
+    IL_0051:  ret
+
+    IL_0052:  ldarg.1
+    IL_0053:  ldnull
+    IL_0054:  cgt.un
+    IL_0056:  ldc.i4.0
+    IL_0057:  ceq
+    IL_0059:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance bool  Equals(class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'> obj) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  4
+    IL_0000:  ldarg.0
+    IL_0001:  brfalse.s  IL_0046
+
+    IL_0003:  ldarg.1
+    IL_0004:  brfalse.s  IL_0044
+
+    IL_0006:  ldarg.0
+    IL_0007:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_000c:  ldarg.1
+    IL_000d:  ldfld      !0 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::A@
+    IL_0012:  call       bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0,
+                                                                                                                      !!0)
+    IL_0017:  brfalse.s  IL_0042
+
+    IL_0019:  ldarg.0
+    IL_001a:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_001f:  ldarg.1
+    IL_0020:  ldfld      !1 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::B@
+    IL_0025:  call       bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0,
+                                                                                                                      !!0)
+    IL_002a:  brfalse.s  IL_0040
+
+    IL_002c:  ldarg.0
+    IL_002d:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_0032:  ldarg.1
+    IL_0033:  ldfld      !2 class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::C@
+    IL_0038:  tail.
+    IL_003a:  call       bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0,
+                                                                                                                      !!0)
+    IL_003f:  ret
+
+    IL_0040:  ldc.i4.0
+    IL_0041:  ret
+
+    IL_0042:  ldc.i4.0
+    IL_0043:  ret
+
+    IL_0044:  ldc.i4.0
+    IL_0045:  ret
+
+    IL_0046:  ldarg.1
+    IL_0047:  ldnull
+    IL_0048:  cgt.un
+    IL_004a:  ldc.i4.0
+    IL_004b:  ceq
+    IL_004d:  ret
+  } 
+
+  .method public hidebysig virtual final 
+          instance bool  Equals(object obj) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  4
+    .locals init (class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'> V_0)
+    IL_0000:  ldarg.1
+    IL_0001:  isinst     class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>
+    IL_0006:  stloc.0
+    IL_0007:  ldloc.0
+    IL_0008:  brfalse.s  IL_0014
+
+    IL_000a:  ldarg.0
+    IL_000b:  ldloc.0
+    IL_000c:  tail.
+    IL_000e:  callvirt   instance bool class '<>f__AnonymousType2430756162`3'j__TPar',!'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType2430756162`3')
+    IL_0013:  ret
+
+    IL_0014:  ldc.i4.0
+    IL_0015:  ret
+  } 
+
+  .property instance !'j__TPar' A()
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) 
+    .get instance !'j__TPar' '<>f__AnonymousType2430756162`3'::get_A()
+  } 
+  .property instance !'j__TPar' B()
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) 
+    .get instance !'j__TPar' '<>f__AnonymousType2430756162`3'::get_B()
+  } 
+  .property instance !'j__TPar' C()
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) 
+    .get instance !'j__TPar' '<>f__AnonymousType2430756162`3'::get_C()
+  } 
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CsharpConsumer.cs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CsharpConsumer.cs
new file mode 100644
index 00000000000..0f459a37a79
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CsharpConsumer.cs
@@ -0,0 +1,32 @@
+namespace CsharpNamespace
+{
+#nullable enable
+    public static class CsharpClass
+    {
+        public static string MyApiWhichHatesNulls(string x)
+        {
+            return x.Length.ToString();
+        }
+
+        public static string JustUseAllOfItHere()
+        {
+            var thisShouldWarn = MyTestModule.nonNullableInputOutputFunc(null);
+            var thisIsPossiblyNullAndIsOk = MyTestModule.nullableStringInputOutputFunc(thisShouldWarn);
+            var thereforeThisShouldWarnAgain = MyTestModule.nonNullableInputOutputFunc(thisIsPossiblyNullAndIsOk);
+
+            string? nullString = null;
+
+            var myStructTuple = (nullString,nullString,1,2,3,4);
+            var thisShouldBeAWarningForSecondTypar = MyTestModule.genericValueTypeTest(myStructTuple);
+            var thisShouldNotSayAnything = MyTestModule.genericValueTypeTest(("I am not nulll",null,1,2,3,4));
+            var thisShouldWarnFor2ndItem = MyTestModule.nonNullableInputOutputFunc(thisShouldNotSayAnything.Item2);
+            var thisIsOkBecauseItem1IsNotNullable = MyTestModule.nonNullableInputOutputFunc(thisShouldNotSayAnything.Item1);
+
+            var refTuple = MyTestModule.genericRefTypeTest(nullString,nullString,1,2,3,4);
+            MyTestModule.genericRefTypeTest(refTuple.Item2,refTuple.Item2,1,2,3,4);
+            
+
+            return MyTestModule.multiArgumentTest(null,null);
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs
new file mode 100644
index 00000000000..7245cd2cd8e
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs
@@ -0,0 +1,10 @@
+module MyTestModule
+
+type Maybe<'T> = 'T | null
+type MaybeString = string | null
+
+let curried3Func (a:MaybeString) (b:string) (c:int) = (a,b,c)
+
+let partiallyAplied (propperString:string) = curried3Func propperString
+
+let secondOutOfTriple (a,b,c) d e : Maybe<_> = b
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.bsl
new file mode 100644
index 00000000000..e785503e5b7
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.bsl
@@ -0,0 +1,203 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .class auto ansi serializable sealed nested assembly beforefieldinit partiallyAplied@8
+         extends class [FSharp.Core]Microsoft.FSharp.Core.OptimizedClosures/FSharpFunc`3>
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .field public string propperString
+    .method assembly specialname rtspecialname 
+            instance void  .ctor(string propperString) cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void class [FSharp.Core]Microsoft.FSharp.Core.OptimizedClosures/FSharpFunc`3>::.ctor()
+      IL_0006:  ldarg.0
+      IL_0007:  ldarg.1
+      IL_0008:  stfld      string MyTestModule/partiallyAplied@8::propperString
+      IL_000d:  ret
+    } 
+
+    .method public strict virtual instance class [runtime]System.Tuple`3 
+            Invoke(string b,
+                   int32 c) cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string MyTestModule/partiallyAplied@8::propperString
+      IL_0006:  ldarg.1
+      IL_0007:  ldarg.2
+      IL_0008:  newobj     instance void class [runtime]System.Tuple`3::.ctor(!0,
+                                                                                                    !1,
+                                                                                                    !2)
+      IL_000d:  ret
+    } 
+
+  } 
+
+  .method public static class [runtime]System.Tuple`3 
+          curried3Func(string a,
+                       string b,
+                       int32 c) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 
+                                                                                                                    00 00 00 00 ) 
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 01 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldarg.1
+    IL_0002:  ldarg.2
+    IL_0003:  newobj     instance void class [runtime]System.Tuple`3::.ctor(!0,
+                                                                                                  !1,
+                                                                                                  !2)
+    IL_0008:  ret
+  } 
+
+  .method public static class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>> 
+          partiallyAplied(string propperString) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 06 00 00 00 01 01 01 01 02 01 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  newobj     instance void MyTestModule/partiallyAplied@8::.ctor(string)
+    IL_0006:  ret
+  } 
+
+  .method public static !!b  secondOutOfTriple(!!a a,
+                                                          !!b b,
+                                                          !!c c,
+                                                          !!d d,
+                                                          !!e e) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 03 00 00 00 01 00 00 00 01 00 
+                                                                                                                    00 00 00 00 ) 
+    .param type a 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    .param type b 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type c 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    .param type d 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    .param type e 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.1
+    IL_0001:  ret
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs
new file mode 100644
index 00000000000..2e52933d1fe
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs
@@ -0,0 +1,25 @@
+module rec MyTestModule
+
+type MaybeString = string | null
+type MaybeMyCustomType = (MyCustomType | null)
+
+type MyCustomType (x: MaybeString, y: string) = 
+
+    static let mutable uglyGlobalMutableString : string = ""
+    static let mutable uglyGlobalMutableNullableString : MaybeString = null
+    static let mutable dict : Map = Map.empty
+
+    member val Nullable = x
+    member val NonNullable = y
+    member val JustSomeInt = 42
+
+    static member GiveMeNull() : MaybeString = null
+    static member GiveMeString() : string = ""
+
+    member this.UnitFunc() = ()
+    member this.GetThis() = this
+    member this.GetThisOrNull() : MaybeMyCustomType = null
+
+    member this.Item
+        with get (index) = dict.[index]
+        and set index value = dict <- dict.Add(index,value)
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.bsl
new file mode 100644
index 00000000000..93c51018c48
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.bsl
@@ -0,0 +1,351 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .class auto ansi serializable nested public Myassembly
+         extends [runtime]System.Object
+  {
+    .custom instance void [runtime]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 )                      
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .field static assembly string uglyGlobalMutableString
+    .field static assembly string uglyGlobalMutableNullableString
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .field static assembly class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 dict
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 02 00 00 ) 
+    .field assembly string Nullable@
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .field assembly string NonNullable@
+    .field assembly int32 JustSomeInt@
+    .field static assembly int32 init@6
+    .method public specialname rtspecialname 
+            instance void  .ctor(string x,
+                                 string y) cil managed
+    {
+      .param [1]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  callvirt   instance void [runtime]System.Object::.ctor()
+      IL_0006:  ldarg.0
+      IL_0007:  pop
+      IL_0008:  ldarg.0
+      IL_0009:  ldarg.1
+      IL_000a:  stfld      string MyTestModule/Myassembly::Nullable@
+      IL_000f:  ldarg.0
+      IL_0010:  ldarg.2
+      IL_0011:  stfld      string MyTestModule/Myassembly::NonNullable@
+      IL_0016:  ldarg.0
+      IL_0017:  ldc.i4.s   42
+      IL_0019:  stfld      int32 MyTestModule/Myassembly::JustSomeInt@
+      IL_001e:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance string  get_Nullable() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string MyTestModule/Myassembly::Nullable@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance string  get_NonNullable() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string MyTestModule/Myassembly::NonNullable@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance int32  get_JustSomeInt() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      int32 MyTestModule/Myassembly::JustSomeInt@
+      IL_0006:  ret
+    } 
+
+    .method public static string  GiveMeNull() cil managed
+    {
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldnull
+      IL_0001:  ret
+    } 
+
+    .method public static string  GiveMeString() cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  ldstr      ""
+      IL_0005:  ret
+    } 
+
+    .method public hidebysig instance void 
+            UnitFunc() cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  ret
+    } 
+
+    .method public hidebysig instance class MyTestModule/Myassembly 
+            GetThis() cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ret
+    } 
+
+    .method public hidebysig instance class MyTestModule/Myassembly 
+            GetThisOrNull() cil managed
+    {
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldnull
+      IL_0001:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance string  get_Item(string index) cil managed
+    {
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .param [1]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  volatile.
+      IL_0002:  ldsfld     int32 MyTestModule/Myassembly::init@6
+      IL_0007:  ldc.i4.4
+      IL_0008:  bge.s      IL_0011
+
+      IL_000a:  call       void [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::FailStaticInit()
+      IL_000f:  br.s       IL_0011
+
+      IL_0011:  ldsfld     class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 MyTestModule/Myassembly::dict
+      IL_0016:  ldarg.1
+      IL_0017:  tail.
+      IL_0019:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2::get_Item(!0)
+      IL_001e:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance void  set_Item(string index,
+                                    string 'value') cil managed
+    {
+      .param [1]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .param [2]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  volatile.
+      IL_0002:  ldsfld     int32 MyTestModule/Myassembly::init@6
+      IL_0007:  ldc.i4.4
+      IL_0008:  bge.s      IL_0011
+
+      IL_000a:  call       void [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::FailStaticInit()
+      IL_000f:  br.s       IL_0011
+
+      IL_0011:  volatile.
+      IL_0013:  ldsfld     int32 MyTestModule/Myassembly::init@6
+      IL_0018:  ldc.i4.4
+      IL_0019:  bge.s      IL_0022
+
+      IL_001b:  call       void [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::FailStaticInit()
+      IL_0020:  br.s       IL_0022
+
+      IL_0022:  ldsfld     class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 MyTestModule/Myassembly::dict
+      IL_0027:  ldarg.1
+      IL_0028:  ldarg.2
+      IL_0029:  callvirt   instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2::Add(!0,
+                                                                                                                                                                                       !1)
+      IL_002e:  stsfld     class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 MyTestModule/Myassembly::dict
+      IL_0033:  ret
+    } 
+
+    .method private specialname rtspecialname static 
+            void  .cctor() cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  ldc.i4.0
+      IL_0001:  stsfld     int32 ''.$MyTestModule::init@
+      IL_0006:  ldsfld     int32 ''.$MyTestModule::init@
+      IL_000b:  pop
+      IL_000c:  ret
+    } 
+
+    .property instance string Nullable()
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .get instance string MyTestModule/Myassembly::get_Nullable()
+    } 
+    .property instance string NonNullable()
+    {
+      .get instance string MyTestModule/Myassembly::get_NonNullable()
+    } 
+    .property instance int32 JustSomeInt()
+    {
+      .get instance int32 MyTestModule/Myassembly::get_JustSomeInt()
+    } 
+    .property instance string Item(string)
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .set instance void MyTestModule/Myassembly::set_Item(string,
+                                                             string)
+      .get instance string MyTestModule/Myassembly::get_Item(string)
+    } 
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .field static assembly int32 init@
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method private specialname rtspecialname static 
+          void  .cctor() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldstr      ""
+    IL_0005:  stsfld     string MyTestModule/Myassembly::uglyGlobalMutableString
+    IL_000a:  ldc.i4.2
+    IL_000b:  volatile.
+    IL_000d:  stsfld     int32 MyTestModule/Myassembly::init@6
+    IL_0012:  ldnull
+    IL_0013:  stsfld     string MyTestModule/Myassembly::uglyGlobalMutableNullableString
+    IL_0018:  ldc.i4.3
+    IL_0019:  volatile.
+    IL_001b:  stsfld     int32 MyTestModule/Myassembly::init@6
+    IL_0020:  call       class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 [FSharp.Core]Microsoft.FSharp.Collections.MapModule::Empty()
+    IL_0025:  stsfld     class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 MyTestModule/Myassembly::dict
+    IL_002a:  ldc.i4.4
+    IL_002b:  volatile.
+    IL_002d:  stsfld     int32 MyTestModule/Myassembly::init@6
+    IL_0032:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs
new file mode 100644
index 00000000000..f3cb30cd05d
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs
@@ -0,0 +1,8 @@
+module MyTestModule
+[]
+let nullableLiteral : string | null = ""
+let notNullStringField : string = ""
+let nullableStringField : string | null = null
+let mutable nullableMutableStringField : string | null = null
+let nullableInt : System.Nullable = System.Nullable()
+let regularInt = 42
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.bsl
new file mode 100644
index 00000000000..b4741b88b22
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.bsl
@@ -0,0 +1,230 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .field public static literal string nullableLiteral = ""
+  .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.LiteralAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .method public specialname static string 
+          get_notNullStringField() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldstr      ""
+    IL_0005:  ret
+  } 
+
+  .method public specialname static string 
+          get_nullableStringField() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldnull
+    IL_0001:  ret
+  } 
+
+  .method public specialname static string 
+          get_nullableMutableStringField() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldsfld     string ''.$MyTestModule::nullableMutableStringField@6
+    IL_0005:  ret
+  } 
+
+  .method public specialname static void 
+          set_nullableMutableStringField(string 'value') cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  stsfld     string ''.$MyTestModule::nullableMutableStringField@6
+    IL_0006:  ret
+  } 
+
+  .method public specialname static valuetype [runtime]System.Nullable`1 
+          get_nullableInt() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  3
+    .locals init (valuetype [runtime]System.Nullable`1 V_0)
+    IL_0000:  ldloc.0
+    IL_0001:  ret
+  } 
+
+  .method public specialname static int32 
+          get_regularInt() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldc.i4.s   42
+    IL_0002:  ret
+  } 
+
+  .method private specialname rtspecialname static 
+          void  .cctor() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldc.i4.0
+    IL_0001:  stsfld     int32 ''.$MyTestModule::init@
+    IL_0006:  ldsfld     int32 ''.$MyTestModule::init@
+    IL_000b:  pop
+    IL_000c:  ret
+  } 
+
+  .property string notNullStringField()
+  {
+    .get string MyTestModule::get_notNullStringField()
+  } 
+  .property string nullableStringField()
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .get string MyTestModule::get_nullableStringField()
+  } 
+  .property string nullableMutableStringField()
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) 
+    .set void MyTestModule::set_nullableMutableStringField(string)
+    .get string MyTestModule::get_nullableMutableStringField()
+  } 
+  .property valuetype [runtime]System.Nullable`1
+          nullableInt()
+  {
+    .get valuetype [runtime]System.Nullable`1 MyTestModule::get_nullableInt()
+  } 
+  .property int32 regularInt()
+  {
+    .get int32 MyTestModule::get_regularInt()
+  } 
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .field static assembly string nullableMutableStringField@6
+  .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .field static assembly int32 init@
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method private specialname rtspecialname static 
+          void  .cctor() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldnull
+    IL_0001:  stsfld     string ''.$MyTestModule::nullableMutableStringField@6
+    IL_0006:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs
new file mode 100644
index 00000000000..5b7efae9b87
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs
@@ -0,0 +1,10 @@
+module MyTestModule
+
+let nonNullableInputOutputFunc (x:string) = x
+let nullableStringInputOutputFunc (x: string | null) = x
+let nonNullableIntFunc (x:int) = x
+let nullableIntFunc (x:System.Nullable) = x
+let genericValueTypeTest (x: struct(string * (string|null) * int * int * int * int)) = x
+let genericRefTypeTest (x: string * (string|null) * int * int * int * int) = x
+let nestedGenericsTest (x: list | null> | null) = x
+let multiArgumentTest (x:string) (y:string | null) = 42
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.bsl
new file mode 100644
index 00000000000..0860bb96bd6
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.bsl
@@ -0,0 +1,214 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .method public static string  nonNullableInputOutputFunc(string x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static string  nullableStringInputOutputFunc(string x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static int32  nonNullableIntFunc(int32 x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static valuetype [runtime]System.Nullable`1 
+          nullableIntFunc(valuetype [runtime]System.Nullable`1 x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static valuetype [runtime]System.ValueTuple`6 
+          genericValueTypeTest(valuetype [runtime]System.ValueTuple`6 x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static class [runtime]System.Tuple`6 
+          genericRefTypeTest(string x_0,
+                             string x_1,
+                             int32 x_2,
+                             int32 x_3,
+                             int32 x_4,
+                             int32 x_5) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
+    .param [2]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    .locals init (class [runtime]System.Tuple`6 V_0)
+    IL_0000:  ldarg.0
+    IL_0001:  ldarg.1
+    IL_0002:  ldarg.2
+    IL_0003:  ldarg.3
+    IL_0004:  ldarg.s    x_4
+    IL_0006:  ldarg.s    x_5
+    IL_0008:  newobj     instance void class [runtime]System.Tuple`6::.ctor(!0,
+                                                                                                                    !1,
+                                                                                                                    !2,
+                                                                                                                    !3,
+                                                                                                                    !4,
+                                                                                                                    !5)
+    IL_000d:  stloc.0
+    IL_000e:  ldloc.0
+    IL_000f:  ret
+  } 
+
+  .method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> 
+          nestedGenericsTest(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static int32  multiArgumentTest(string x,
+                                                 string y) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+    .param [2]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldc.i4.s   42
+    IL_0002:  ret
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs
new file mode 100644
index 00000000000..5b7efae9b87
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs
@@ -0,0 +1,10 @@
+module MyTestModule
+
+let nonNullableInputOutputFunc (x:string) = x
+let nullableStringInputOutputFunc (x: string | null) = x
+let nonNullableIntFunc (x:int) = x
+let nullableIntFunc (x:System.Nullable) = x
+let genericValueTypeTest (x: struct(string * (string|null) * int * int * int * int)) = x
+let genericRefTypeTest (x: string * (string|null) * int * int * int * int) = x
+let nestedGenericsTest (x: list | null> | null) = x
+let multiArgumentTest (x:string) (y:string | null) = 42
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.bsl
new file mode 100644
index 00000000000..6ffc03c1573
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.bsl
@@ -0,0 +1,211 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .method public static string  nonNullableInputOutputFunc(string x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static string  nullableStringInputOutputFunc(string x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static int32  nonNullableIntFunc(int32 x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static valuetype [runtime]System.Nullable`1 
+          nullableIntFunc(valuetype [runtime]System.Nullable`1 x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static valuetype [runtime]System.ValueTuple`6 
+          genericValueTypeTest(valuetype [runtime]System.ValueTuple`6 x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static class [runtime]System.Tuple`6 
+          genericRefTypeTest(string x_0,
+                             string x_1,
+                             int32 x_2,
+                             int32 x_3,
+                             int32 x_4,
+                             int32 x_5) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
+    .param [2]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldarg.1
+    IL_0002:  ldarg.2
+    IL_0003:  ldarg.3
+    IL_0004:  ldarg.s    x_4
+    IL_0006:  ldarg.s    x_5
+    IL_0008:  newobj     instance void class [runtime]System.Tuple`6::.ctor(!0,
+                                                                                                                    !1,
+                                                                                                                    !2,
+                                                                                                                    !3,
+                                                                                                                    !4,
+                                                                                                                    !5)
+    IL_000d:  ret
+  } 
+
+  .method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> 
+          nestedGenericsTest(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static int32  multiArgumentTest(string x,
+                                                 string y) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+    .param [2]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldc.i4.s   42
+    IL_0002:  ret
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs
new file mode 100644
index 00000000000..f6038521066
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs
@@ -0,0 +1,33 @@
+module TestModule
+
+[]
+[]
+type MyNullableOption<'T when 'T:null> = 
+    | MyNone
+    | MySome of value:'T
+
+let mapPossiblyNullable f myOpt =
+    match myOpt with
+    | MyNone -> MyNone
+    | MySome x -> MySome (f x)
+
+[]
+[]
+type MyOptionWhichCannotHaveNullInTheInside<'T when 'T:not null> = 
+    | MyNotNullNone
+    | MyNotNullSome of value:'T
+
+let mapNotNullableContents f myOpt =
+    match myOpt with
+    | MyNotNullNone -> MyNotNullNone
+    | MyNotNullSome x -> MyNotNullSome (f x)
+
+[]
+type MyStructOption<'T when 'T: not null> = 
+    | MyStructNone
+    | MyStructSome of nestedGenericField : list> * notNullField2 : string * canBeNullField : (string | null) * notNullField1 : 'T
+
+let mapStructContents f myOpt =
+    match myOpt with
+    | MyStructNone -> MyStructNone
+    | MyStructSome(ngf,s,ns,x) -> MyStructSome (ngf,s,ns,f x)
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl
new file mode 100644
index 00000000000..7c42b07d649
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl
@@ -0,0 +1,1040 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed TestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .class auto autochar serializable sealed nested public beforefieldinit MyNullableOption`1
+         extends [runtime]System.Object
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationRepresentationAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilationRepresentationFlags) = ( 01 00 08 00 00 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                   61 79 28 29 2C 6E 71 7D 00 00 )                   
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type T 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .class abstract auto ansi sealed nested public Tags
+           extends [runtime]System.Object
+    {
+      .param type T 
+        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .field public static literal int32 MyNone = int32(0x00000000)
+      .field public static literal int32 MySome = int32(0x00000001)
+    } 
+
+    .field assembly initonly !T _value
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .method assembly specialname rtspecialname 
+            instance void  .ctor() cil managed
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                              class [runtime]System.Type) = ( 01 00 E0 07 00 00 1D 54 65 73 74 4D 6F 64 75 6C   
+                                                                                                                               65 2B 4D 79 4E 75 6C 6C 61 62 6C 65 4F 70 74 69   
+                                                                                                                               6F 6E 60 31 00 00 )                               
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void [runtime]System.Object::.ctor()
+      IL_0006:  ret
+    } 
+
+    .method public static class TestModule/MyNullableOption`1 
+            get_MyNone() cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldnull
+      IL_0001:  ret
+    } 
+
+    .method public static class TestModule/MyNullableOption`1 
+            NewMySome(!T _value) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  newobj     instance void class TestModule/MyNullableOption`1::.ctor(!0)
+      IL_0006:  ret
+    } 
+
+    .method assembly specialname rtspecialname 
+            instance void  .ctor(!T _value) cil managed
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                              class [runtime]System.Type) = ( 01 00 60 06 00 00 1D 54 65 73 74 4D 6F 64 75 6C   
+                                                                                                                               65 2B 4D 79 4E 75 6C 6C 61 62 6C 65 4F 70 74 69   
+                                                                                                                               6F 6E 60 31 00 00 )                               
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void [runtime]System.Object::.ctor()
+      IL_0006:  ldarg.0
+      IL_0007:  ldarg.1
+      IL_0008:  stfld      !0 class TestModule/MyNullableOption`1::_value
+      IL_000d:  ret
+    } 
+
+    .method public hidebysig instance !T 
+            get_value() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      !0 class TestModule/MyNullableOption`1::_value
+      IL_0006:  ret
+    } 
+
+    .method public static int32  GetTag(class TestModule/MyNullableOption`1 A_0) cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  brfalse.s  IL_0006
+
+      IL_0003:  ldc.i4.1
+      IL_0004:  br.s       IL_0007
+
+      IL_0006:  ldc.i4.0
+      IL_0007:  ret
+    } 
+
+    .method assembly hidebysig specialname 
+            instance object  __DebugDisplay() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+0.8A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_0015:  ret
+    } 
+
+    .method public strict virtual instance string 
+            ToString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class TestModule/MyNullableOption`1>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_0015:  ret
+    } 
+
+    .property class TestModule/MyNullableOption`1
+            MyNone()
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get class TestModule/MyNullableOption`1 TestModule/MyNullableOption`1::get_MyNone()
+    } 
+    .property instance !T 'value'()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance !T TestModule/MyNullableOption`1::get_value()
+    } 
+  } 
+
+  .class auto autochar serializable sealed nested public beforefieldinit MyOptionWhichCannotHaveNullInTheInside`1
+         extends [runtime]System.Object
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationRepresentationAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilationRepresentationFlags) = ( 01 00 08 00 00 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                   61 79 28 29 2C 6E 71 7D 00 00 )                   
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type T 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .class abstract auto ansi sealed nested public Tags
+           extends [runtime]System.Object
+    {
+      .param type T 
+        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .field public static literal int32 MyNotNullNone = int32(0x00000000)
+      .field public static literal int32 MyNotNullSome = int32(0x00000001)
+    } 
+
+    .field assembly initonly !T _value
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .method assembly specialname rtspecialname 
+            instance void  .ctor() cil managed
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                              class [runtime]System.Type) = ( 01 00 E0 07 00 00 33 54 65 73 74 4D 6F 64 75 6C   
+                                                                                                                               65 2B 4D 79 4F 70 74 69 6F 6E 57 68 69 63 68 43   
+                                                                                                                               61 6E 6E 6F 74 48 61 76 65 4E 75 6C 6C 49 6E 54   
+                                                                                                                               68 65 49 6E 73 69 64 65 60 31 00 00 )             
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void [runtime]System.Object::.ctor()
+      IL_0006:  ret
+    } 
+
+    .method public static class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 
+            get_MyNotNullNone() cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldnull
+      IL_0001:  ret
+    } 
+
+    .method public static class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 
+            NewMyNotNullSome(!T _value) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  newobj     instance void class TestModule/MyOptionWhichCannotHaveNullInTheInside`1::.ctor(!0)
+      IL_0006:  ret
+    } 
+
+    .method assembly specialname rtspecialname 
+            instance void  .ctor(!T _value) cil managed
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                              class [runtime]System.Type) = ( 01 00 60 06 00 00 33 54 65 73 74 4D 6F 64 75 6C   
+                                                                                                                               65 2B 4D 79 4F 70 74 69 6F 6E 57 68 69 63 68 43   
+                                                                                                                               61 6E 6E 6F 74 48 61 76 65 4E 75 6C 6C 49 6E 54   
+                                                                                                                               68 65 49 6E 73 69 64 65 60 31 00 00 )             
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void [runtime]System.Object::.ctor()
+      IL_0006:  ldarg.0
+      IL_0007:  ldarg.1
+      IL_0008:  stfld      !0 class TestModule/MyOptionWhichCannotHaveNullInTheInside`1::_value
+      IL_000d:  ret
+    } 
+
+    .method public hidebysig instance !T 
+            get_value() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      !0 class TestModule/MyOptionWhichCannotHaveNullInTheInside`1::_value
+      IL_0006:  ret
+    } 
+
+    .method public static int32  GetTag(class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 A_0) cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  brfalse.s  IL_0006
+
+      IL_0003:  ldc.i4.1
+      IL_0004:  br.s       IL_0007
+
+      IL_0006:  ldc.i4.0
+      IL_0007:  ret
+    } 
+
+    .method assembly hidebysig specialname 
+            instance object  __DebugDisplay() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+0.8A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_0015:  ret
+    } 
+
+    .method public strict virtual instance string 
+            ToString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class TestModule/MyOptionWhichCannotHaveNullInTheInside`1>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_0015:  ret
+    } 
+
+    .property class TestModule/MyOptionWhichCannotHaveNullInTheInside`1
+            MyNotNullNone()
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_MyNotNullNone()
+    } 
+    .property instance !T 'value'()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance !T TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_value()
+    } 
+  } 
+
+  .class sequential autochar serializable sealed nested public beforefieldinit MyStructOption`1
+         extends [runtime]System.ValueType
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                   61 79 28 29 2C 6E 71 7D 00 00 )                   
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type T 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .class abstract auto ansi sealed nested public Tags
+           extends [runtime]System.Object
+    {
+      .param type T 
+        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .field public static literal int32 MyStructNone = int32(0x00000000)
+      .field public static literal int32 MyStructSome = int32(0x00000001)
+    } 
+
+    .field assembly class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> _nestedGenericField
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly string _notNullField2
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly string _canBeNullField
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly !T _notNullField1
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly int32 _tag
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .method public static valuetype TestModule/MyStructOption`1 
+            get_MyStructNone() cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldc.i4.0
+      IL_0001:  newobj     instance void valuetype TestModule/MyStructOption`1::.ctor(int32)
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsMyStructNone() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
+      IL_0006:  ldc.i4.0
+      IL_0007:  ceq
+      IL_0009:  ret
+    } 
+
+    .method public static valuetype TestModule/MyStructOption`1 
+            NewMyStructSome(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> _nestedGenericField,
+                            string _notNullField2,
+                            string _canBeNullField,
+                            !T _notNullField1) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
+      .param [1]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
+      .param [3]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  5
+      .locals init (valuetype TestModule/MyStructOption`1 V_0)
+      IL_0000:  ldloca.s   V_0
+      IL_0002:  initobj    valuetype TestModule/MyStructOption`1
+      IL_0008:  ldloca.s   V_0
+      IL_000a:  ldc.i4.1
+      IL_000b:  stfld      int32 valuetype TestModule/MyStructOption`1::_tag
+      IL_0010:  ldloca.s   V_0
+      IL_0012:  ldarg.0
+      IL_0013:  stfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
+      IL_0018:  ldloca.s   V_0
+      IL_001a:  ldarg.1
+      IL_001b:  stfld      string valuetype TestModule/MyStructOption`1::_notNullField2
+      IL_0020:  ldloca.s   V_0
+      IL_0022:  ldarg.2
+      IL_0023:  stfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
+      IL_0028:  ldloca.s   V_0
+      IL_002a:  ldarg.3
+      IL_002b:  stfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
+      IL_0030:  ldloc.0
+      IL_0031:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsMyStructSome() cil managed
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
+                                                                                              string[]) = ( 01 00 01 04 00 00 00 0D 6E 6F 74 4E 75 6C 6C 46   
+                                                                                                            69 65 6C 64 32 0D 6E 6F 74 4E 75 6C 6C 46 69 65   
+                                                                                                            6C 64 31 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C   
+                                                                                                            64 32 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C 64   
+                                                                                                            31 00 00 )                                        
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
+      IL_0006:  ldc.i4.1
+      IL_0007:  ceq
+      IL_0009:  ret
+    } 
+
+    .method assembly specialname rtspecialname 
+            instance void  .ctor(int32 _tag) cil managed
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                              class [runtime]System.Type) = ( 01 00 60 06 00 00 1B 54 65 73 74 4D 6F 64 75 6C   
+                                                                                                                               65 2B 4D 79 53 74 72 75 63 74 4F 70 74 69 6F 6E   
+                                                                                                                               60 31 00 00 )                                     
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldarg.1
+      IL_0002:  stfld      int32 valuetype TestModule/MyStructOption`1::_tag
+      IL_0007:  ret
+    } 
+
+    .method public hidebysig instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> 
+            get_nestedGenericField() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance string 
+            get_notNullField2() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string valuetype TestModule/MyStructOption`1::_notNullField2
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance string 
+            get_canBeNullField() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance !T 
+            get_notNullField1() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance int32 
+            get_Tag() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      int32 valuetype TestModule/MyStructOption`1::_tag
+      IL_0006:  ret
+    } 
+
+    .method assembly hidebysig specialname 
+            instance object  __DebugDisplay() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+0.8A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  ldobj      valuetype TestModule/MyStructOption`1
+      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_001a:  ret
+    } 
+
+    .method public strict virtual instance string 
+            ToString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,valuetype TestModule/MyStructOption`1>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  ldobj      valuetype TestModule/MyStructOption`1
+      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_001a:  ret
+    } 
+
+    .property instance int32 Tag()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance int32 TestModule/MyStructOption`1::get_Tag()
+    } 
+    .property valuetype TestModule/MyStructOption`1
+            MyStructNone()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get valuetype TestModule/MyStructOption`1 TestModule/MyStructOption`1::get_MyStructNone()
+    } 
+    .property instance bool IsMyStructNone()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool TestModule/MyStructOption`1::get_IsMyStructNone()
+    } 
+    .property instance bool IsMyStructSome()
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
+                                                                                              string[]) = ( 01 00 01 04 00 00 00 0D 6E 6F 74 4E 75 6C 6C 46   
+                                                                                                            69 65 6C 64 32 0D 6E 6F 74 4E 75 6C 6C 46 69 65   
+                                                                                                            6C 64 31 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C   
+                                                                                                            64 32 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C 64   
+                                                                                                            31 00 00 )                                        
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool TestModule/MyStructOption`1::get_IsMyStructSome()
+    } 
+    .property instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>
+            nestedGenericField()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> TestModule/MyStructOption`1::get_nestedGenericField()
+    } 
+    .property instance string notNullField2()
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance string TestModule/MyStructOption`1::get_notNullField2()
+    } 
+    .property instance string canBeNullField()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 02 00 00 00 00 00 ) 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance string TestModule/MyStructOption`1::get_canBeNullField()
+    } 
+    .property instance !T notNullField1()
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 03 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance !T TestModule/MyStructOption`1::get_notNullField1()
+    } 
+  } 
+
+  .method public static class TestModule/MyNullableOption`1 
+          mapPossiblyNullable(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f,
+                                         class TestModule/MyNullableOption`1 myOpt) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+    .param type a 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .param type b 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    
+    .maxstack  4
+    .locals init (class TestModule/MyNullableOption`1 V_0,
+             class TestModule/MyNullableOption`1 V_1,
+             !!a V_2)
+    IL_0000:  ldarg.1
+    IL_0001:  stloc.0
+    IL_0002:  ldloc.0
+    IL_0003:  brfalse.s  IL_0007
+
+    IL_0005:  br.s       IL_0009
+
+    IL_0007:  ldnull
+    IL_0008:  ret
+
+    IL_0009:  ldloc.0
+    IL_000a:  stloc.1
+    IL_000b:  ldloc.1
+    IL_000c:  ldfld      !0 class TestModule/MyNullableOption`1::_value
+    IL_0011:  stloc.2
+    IL_0012:  ldarg.0
+    IL_0013:  ldloc.2
+    IL_0014:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+    IL_0019:  call       class TestModule/MyNullableOption`1 class TestModule/MyNullableOption`1::NewMySome(!0)
+    IL_001e:  ret
+  } 
+
+  .method public static class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 
+          mapNotNullableContents(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f,
+                                      class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 myOpt) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+    .param type a 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type b 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    
+    .maxstack  4
+    .locals init (class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 V_0,
+             class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 V_1,
+             !!a V_2)
+    IL_0000:  ldarg.1
+    IL_0001:  stloc.0
+    IL_0002:  ldloc.0
+    IL_0003:  brfalse.s  IL_0007
+
+    IL_0005:  br.s       IL_0009
+
+    IL_0007:  ldnull
+    IL_0008:  ret
+
+    IL_0009:  ldloc.0
+    IL_000a:  stloc.1
+    IL_000b:  ldloc.1
+    IL_000c:  ldfld      !0 class TestModule/MyOptionWhichCannotHaveNullInTheInside`1::_value
+    IL_0011:  stloc.2
+    IL_0012:  ldarg.0
+    IL_0013:  ldloc.2
+    IL_0014:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+    IL_0019:  call       class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 class TestModule/MyOptionWhichCannotHaveNullInTheInside`1::NewMyNotNullSome(!0)
+    IL_001e:  ret
+  } 
+
+  .method public static valuetype TestModule/MyStructOption`1 
+          mapStructContents(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f,
+                                 valuetype TestModule/MyStructOption`1 myOpt) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+    .param type a 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type b 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    .param [2]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    
+    .maxstack  7
+    .locals init (valuetype TestModule/MyStructOption`1 V_0,
+             !!a V_1,
+             string V_2,
+             string V_3,
+             class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> V_4)
+    IL_0000:  ldarg.1
+    IL_0001:  stloc.0
+    IL_0002:  ldloca.s   V_0
+    IL_0004:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
+    IL_0009:  ldc.i4.1
+    IL_000a:  bne.un.s   IL_000e
+
+    IL_000c:  br.s       IL_0014
+
+    IL_000e:  call       valuetype TestModule/MyStructOption`1 valuetype TestModule/MyStructOption`1::get_MyStructNone()
+    IL_0013:  ret
+
+    IL_0014:  ldloca.s   V_0
+    IL_0016:  ldfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
+    IL_001b:  stloc.1
+    IL_001c:  ldloca.s   V_0
+    IL_001e:  ldfld      string valuetype TestModule/MyStructOption`1::_notNullField2
+    IL_0023:  stloc.2
+    IL_0024:  ldloca.s   V_0
+    IL_0026:  ldfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
+    IL_002b:  stloc.3
+    IL_002c:  ldloca.s   V_0
+    IL_002e:  ldfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
+    IL_0033:  stloc.s    V_4
+    IL_0035:  ldloc.s    V_4
+    IL_0037:  ldloc.2
+    IL_0038:  ldloc.3
+    IL_0039:  ldarg.0
+    IL_003a:  ldloc.1
+    IL_003b:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+    IL_0040:  call       valuetype TestModule/MyStructOption`1 valuetype TestModule/MyStructOption`1::NewMyStructSome(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>,
+                                                                                                                               string,
+                                                                                                                               string,
+                                                                                                                               !0)
+    IL_0045:  ret
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$TestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi serializable sealed System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes
+       extends [runtime]System.Enum
+{
+  .custom instance void [runtime]System.FlagsAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public specialname rtspecialname int32 value__
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes All = int32(0xFFFFFFFF)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes None = int32(0x00000000)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicParameterlessConstructor = int32(0x00000001)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicConstructors = int32(0x00000003)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicConstructors = int32(0x00000004)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicMethods = int32(0x00000008)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicMethods = int32(0x00000010)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicFields = int32(0x00000020)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicFields = int32(0x00000040)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicNestedTypes = int32(0x00000080)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicNestedTypes = int32(0x00000100)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicProperties = int32(0x00000200)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicProperties = int32(0x00000400)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicEvents = int32(0x00000800)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicEvents = int32(0x00001000)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes Interfaces = int32(0x00002000)
+} 
+
+.class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute
+       extends [runtime]System.Attribute
+{
+  .field private valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field private class [runtime]System.Type Type@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType,
+                               class [runtime]System.Type Type) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::MemberType@
+    IL_000d:  ldarg.0
+    IL_000e:  ldarg.2
+    IL_000f:  stfld      class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::Type@
+    IL_0014:  ret
+  } 
+
+  .method public hidebysig specialname instance class [runtime]System.Type 
+          get_Type() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::Type@
+    IL_0006:  ret
+  } 
+
+  .method public hidebysig specialname instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes 
+          get_MemberType() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::MemberType@
+    IL_0006:  ret
+  } 
+
+  .property instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes
+          MemberType()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::get_MemberType()
+  } 
+  .property instance class [runtime]System.Type
+          Type()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::get_Type()
+  } 
+} 
+
+.class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute
+       extends [runtime]System.Attribute
+{
+  .field private bool ReturnValue@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field private string[] Members@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(bool ReturnValue,
+                               string[] Members) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      bool System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::ReturnValue@
+    IL_000d:  ldarg.0
+    IL_000e:  ldarg.2
+    IL_000f:  stfld      string[] System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::Members@
+    IL_0014:  ret
+  } 
+
+  .method public hidebysig specialname instance string[] 
+          get_Members() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      string[] System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::Members@
+    IL_0006:  ret
+  } 
+
+  .method public hidebysig specialname instance bool 
+          get_ReturnValue() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      bool System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::ReturnValue@
+    IL_0006:  ret
+  } 
+
+  .property instance bool ReturnValue()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance bool System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::get_ReturnValue()
+  } 
+  .property instance string[] Members()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance string[] System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::get_Members()
+  } 
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl
new file mode 100644
index 00000000000..8520df5ca9f
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl
@@ -0,0 +1,881 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed TestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .class auto autochar serializable sealed nested public beforefieldinit MyNullableOption`1
+         extends [runtime]System.Object
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationRepresentationAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilationRepresentationFlags) = ( 01 00 08 00 00 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                         61 79 28 29 2C 6E 71 7D 00 00 )                   
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type T 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .class abstract auto ansi sealed nested public Tags
+           extends [runtime]System.Object
+    {
+      .param type T 
+        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .field public static literal int32 MyNone = int32(0x00000000)
+      .field public static literal int32 MySome = int32(0x00000001)
+    } 
+
+    .field assembly initonly !T _value
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .method assembly specialname rtspecialname 
+            instance void  .ctor() cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                              class [runtime]System.Type) = ( 01 00 E0 07 00 00 1D 54 65 73 74 4D 6F 64 75 6C   
+                                                                                                                                                     65 2B 4D 79 4E 75 6C 6C 61 62 6C 65 4F 70 74 69   
+                                                                                                                                                     6F 6E 60 31 00 00 )                               
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void [runtime]System.Object::.ctor()
+      IL_0006:  ret
+    } 
+
+    .method public static class TestModule/MyNullableOption`1 
+            get_MyNone() cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldnull
+      IL_0001:  ret
+    } 
+
+    .method public static class TestModule/MyNullableOption`1 
+            NewMySome(!T _value) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  newobj     instance void class TestModule/MyNullableOption`1::.ctor(!0)
+      IL_0006:  ret
+    } 
+
+    .method assembly specialname rtspecialname 
+            instance void  .ctor(!T _value) cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                              class [runtime]System.Type) = ( 01 00 60 06 00 00 1D 54 65 73 74 4D 6F 64 75 6C   
+                                                                                                                                                     65 2B 4D 79 4E 75 6C 6C 61 62 6C 65 4F 70 74 69   
+                                                                                                                                                     6F 6E 60 31 00 00 )                               
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void [runtime]System.Object::.ctor()
+      IL_0006:  ldarg.0
+      IL_0007:  ldarg.1
+      IL_0008:  stfld      !0 class TestModule/MyNullableOption`1::_value
+      IL_000d:  ret
+    } 
+
+    .method public hidebysig instance !T 
+            get_value() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      !0 class TestModule/MyNullableOption`1::_value
+      IL_0006:  ret
+    } 
+
+    .method public static int32  GetTag(class TestModule/MyNullableOption`1 A_0) cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  brfalse.s  IL_0006
+
+      IL_0003:  ldc.i4.1
+      IL_0004:  br.s       IL_0007
+
+      IL_0006:  ldc.i4.0
+      IL_0007:  ret
+    } 
+
+    .method assembly hidebysig specialname 
+            instance object  __DebugDisplay() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+0.8A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_0015:  ret
+    } 
+
+    .method public strict virtual instance string 
+            ToString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class TestModule/MyNullableOption`1>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_0015:  ret
+    } 
+
+    .property class TestModule/MyNullableOption`1
+            MyNone()
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get class TestModule/MyNullableOption`1 TestModule/MyNullableOption`1::get_MyNone()
+    } 
+    .property instance !T 'value'()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance !T TestModule/MyNullableOption`1::get_value()
+    } 
+  } 
+
+  .class auto autochar serializable sealed nested public beforefieldinit MyOptionWhichCannotHaveNullInTheInside`1
+         extends [runtime]System.Object
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationRepresentationAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilationRepresentationFlags) = ( 01 00 08 00 00 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                         61 79 28 29 2C 6E 71 7D 00 00 )                   
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type T 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .class abstract auto ansi sealed nested public Tags
+           extends [runtime]System.Object
+    {
+      .param type T 
+        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .field public static literal int32 MyNotNullNone = int32(0x00000000)
+      .field public static literal int32 MyNotNullSome = int32(0x00000001)
+    } 
+
+    .field assembly initonly !T _value
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .method assembly specialname rtspecialname 
+            instance void  .ctor() cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                              class [runtime]System.Type) = ( 01 00 E0 07 00 00 33 54 65 73 74 4D 6F 64 75 6C   
+                                                                                                                                                     65 2B 4D 79 4F 70 74 69 6F 6E 57 68 69 63 68 43   
+                                                                                                                                                     61 6E 6E 6F 74 48 61 76 65 4E 75 6C 6C 49 6E 54   
+                                                                                                                                                     68 65 49 6E 73 69 64 65 60 31 00 00 )             
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void [runtime]System.Object::.ctor()
+      IL_0006:  ret
+    } 
+
+    .method public static class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 
+            get_MyNotNullNone() cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldnull
+      IL_0001:  ret
+    } 
+
+    .method public static class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 
+            NewMyNotNullSome(!T _value) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  newobj     instance void class TestModule/MyOptionWhichCannotHaveNullInTheInside`1::.ctor(!0)
+      IL_0006:  ret
+    } 
+
+    .method assembly specialname rtspecialname 
+            instance void  .ctor(!T _value) cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                              class [runtime]System.Type) = ( 01 00 60 06 00 00 33 54 65 73 74 4D 6F 64 75 6C   
+                                                                                                                                                     65 2B 4D 79 4F 70 74 69 6F 6E 57 68 69 63 68 43   
+                                                                                                                                                     61 6E 6E 6F 74 48 61 76 65 4E 75 6C 6C 49 6E 54   
+                                                                                                                                                     68 65 49 6E 73 69 64 65 60 31 00 00 )             
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void [runtime]System.Object::.ctor()
+      IL_0006:  ldarg.0
+      IL_0007:  ldarg.1
+      IL_0008:  stfld      !0 class TestModule/MyOptionWhichCannotHaveNullInTheInside`1::_value
+      IL_000d:  ret
+    } 
+
+    .method public hidebysig instance !T 
+            get_value() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      !0 class TestModule/MyOptionWhichCannotHaveNullInTheInside`1::_value
+      IL_0006:  ret
+    } 
+
+    .method public static int32  GetTag(class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 A_0) cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  brfalse.s  IL_0006
+
+      IL_0003:  ldc.i4.1
+      IL_0004:  br.s       IL_0007
+
+      IL_0006:  ldc.i4.0
+      IL_0007:  ret
+    } 
+
+    .method assembly hidebysig specialname 
+            instance object  __DebugDisplay() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+0.8A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_0015:  ret
+    } 
+
+    .method public strict virtual instance string 
+            ToString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class TestModule/MyOptionWhichCannotHaveNullInTheInside`1>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_0015:  ret
+    } 
+
+    .property class TestModule/MyOptionWhichCannotHaveNullInTheInside`1
+            MyNotNullNone()
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_MyNotNullNone()
+    } 
+    .property instance !T 'value'()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance !T TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_value()
+    } 
+  } 
+
+  .class sequential autochar serializable sealed nested public beforefieldinit MyStructOption`1
+         extends [runtime]System.ValueType
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                         61 79 28 29 2C 6E 71 7D 00 00 )                   
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type T 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .class abstract auto ansi sealed nested public Tags
+           extends [runtime]System.Object
+    {
+      .param type T 
+        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .field public static literal int32 MyStructNone = int32(0x00000000)
+      .field public static literal int32 MyStructSome = int32(0x00000001)
+    } 
+
+    .field assembly class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> _nestedGenericField
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly string _notNullField2
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly string _canBeNullField
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly !T _notNullField1
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly int32 _tag
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .method public static valuetype TestModule/MyStructOption`1 
+            get_MyStructNone() cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldc.i4.0
+      IL_0001:  newobj     instance void valuetype TestModule/MyStructOption`1::.ctor(int32)
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsMyStructNone() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
+      IL_0006:  ldc.i4.0
+      IL_0007:  ceq
+      IL_0009:  ret
+    } 
+
+    .method public static valuetype TestModule/MyStructOption`1 
+            NewMyStructSome(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> _nestedGenericField,
+                            string _notNullField2,
+                            string _canBeNullField,
+                            !T _notNullField1) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
+      .param [1]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
+      .param [3]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  5
+      .locals init (valuetype TestModule/MyStructOption`1 V_0)
+      IL_0000:  ldloca.s   V_0
+      IL_0002:  initobj    valuetype TestModule/MyStructOption`1
+      IL_0008:  ldloca.s   V_0
+      IL_000a:  ldc.i4.1
+      IL_000b:  stfld      int32 valuetype TestModule/MyStructOption`1::_tag
+      IL_0010:  ldloca.s   V_0
+      IL_0012:  ldarg.0
+      IL_0013:  stfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
+      IL_0018:  ldloca.s   V_0
+      IL_001a:  ldarg.1
+      IL_001b:  stfld      string valuetype TestModule/MyStructOption`1::_notNullField2
+      IL_0020:  ldloca.s   V_0
+      IL_0022:  ldarg.2
+      IL_0023:  stfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
+      IL_0028:  ldloca.s   V_0
+      IL_002a:  ldarg.3
+      IL_002b:  stfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
+      IL_0030:  ldloc.0
+      IL_0031:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsMyStructSome() cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
+                                                                                                              string[]) = ( 01 00 01 04 00 00 00 0D 6E 6F 74 4E 75 6C 6C 46   
+                                                                                                                            69 65 6C 64 32 0D 6E 6F 74 4E 75 6C 6C 46 69 65   
+                                                                                                                            6C 64 31 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C   
+                                                                                                                            64 32 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C 64   
+                                                                                                                            31 00 00 )                                        
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
+      IL_0006:  ldc.i4.1
+      IL_0007:  ceq
+      IL_0009:  ret
+    } 
+
+    .method assembly specialname rtspecialname 
+            instance void  .ctor(int32 _tag) cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                              class [runtime]System.Type) = ( 01 00 60 06 00 00 1B 54 65 73 74 4D 6F 64 75 6C   
+                                                                                                                                                     65 2B 4D 79 53 74 72 75 63 74 4F 70 74 69 6F 6E   
+                                                                                                                                                     60 31 00 00 )                                     
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldarg.1
+      IL_0002:  stfld      int32 valuetype TestModule/MyStructOption`1::_tag
+      IL_0007:  ret
+    } 
+
+    .method public hidebysig instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> 
+            get_nestedGenericField() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance string 
+            get_notNullField2() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string valuetype TestModule/MyStructOption`1::_notNullField2
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance string 
+            get_canBeNullField() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance !T 
+            get_notNullField1() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance int32 
+            get_Tag() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      int32 valuetype TestModule/MyStructOption`1::_tag
+      IL_0006:  ret
+    } 
+
+    .method assembly hidebysig specialname 
+            instance object  __DebugDisplay() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+0.8A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  ldobj      valuetype TestModule/MyStructOption`1
+      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_001a:  ret
+    } 
+
+    .method public strict virtual instance string 
+            ToString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,valuetype TestModule/MyStructOption`1>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  ldobj      valuetype TestModule/MyStructOption`1
+      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_001a:  ret
+    } 
+
+    .property instance int32 Tag()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance int32 TestModule/MyStructOption`1::get_Tag()
+    } 
+    .property valuetype TestModule/MyStructOption`1
+            MyStructNone()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get valuetype TestModule/MyStructOption`1 TestModule/MyStructOption`1::get_MyStructNone()
+    } 
+    .property instance bool IsMyStructNone()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool TestModule/MyStructOption`1::get_IsMyStructNone()
+    } 
+    .property instance bool IsMyStructSome()
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
+                                                                                                              string[]) = ( 01 00 01 04 00 00 00 0D 6E 6F 74 4E 75 6C 6C 46   
+                                                                                                                            69 65 6C 64 32 0D 6E 6F 74 4E 75 6C 6C 46 69 65   
+                                                                                                                            6C 64 31 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C   
+                                                                                                                            64 32 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C 64   
+                                                                                                                            31 00 00 )                                        
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool TestModule/MyStructOption`1::get_IsMyStructSome()
+    } 
+    .property instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>
+            nestedGenericField()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> TestModule/MyStructOption`1::get_nestedGenericField()
+    } 
+    .property instance string notNullField2()
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance string TestModule/MyStructOption`1::get_notNullField2()
+    } 
+    .property instance string canBeNullField()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 02 00 00 00 00 00 ) 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance string TestModule/MyStructOption`1::get_canBeNullField()
+    } 
+    .property instance !T notNullField1()
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 03 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance !T TestModule/MyStructOption`1::get_notNullField1()
+    } 
+  } 
+
+  .method public static class TestModule/MyNullableOption`1 
+          mapPossiblyNullable(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f,
+                                         class TestModule/MyNullableOption`1 myOpt) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+    .param type a 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .param type b 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    
+    .maxstack  4
+    .locals init (class TestModule/MyNullableOption`1 V_0,
+             class TestModule/MyNullableOption`1 V_1,
+             !!a V_2)
+    IL_0000:  ldarg.1
+    IL_0001:  stloc.0
+    IL_0002:  ldloc.0
+    IL_0003:  brfalse.s  IL_0007
+
+    IL_0005:  br.s       IL_0009
+
+    IL_0007:  ldnull
+    IL_0008:  ret
+
+    IL_0009:  ldloc.0
+    IL_000a:  stloc.1
+    IL_000b:  ldloc.1
+    IL_000c:  ldfld      !0 class TestModule/MyNullableOption`1::_value
+    IL_0011:  stloc.2
+    IL_0012:  ldarg.0
+    IL_0013:  ldloc.2
+    IL_0014:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+    IL_0019:  call       class TestModule/MyNullableOption`1 class TestModule/MyNullableOption`1::NewMySome(!0)
+    IL_001e:  ret
+  } 
+
+  .method public static class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 
+          mapNotNullableContents(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f,
+                                      class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 myOpt) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+    .param type a 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type b 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    
+    .maxstack  4
+    .locals init (class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 V_0,
+             class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 V_1,
+             !!a V_2)
+    IL_0000:  ldarg.1
+    IL_0001:  stloc.0
+    IL_0002:  ldloc.0
+    IL_0003:  brfalse.s  IL_0007
+
+    IL_0005:  br.s       IL_0009
+
+    IL_0007:  ldnull
+    IL_0008:  ret
+
+    IL_0009:  ldloc.0
+    IL_000a:  stloc.1
+    IL_000b:  ldloc.1
+    IL_000c:  ldfld      !0 class TestModule/MyOptionWhichCannotHaveNullInTheInside`1::_value
+    IL_0011:  stloc.2
+    IL_0012:  ldarg.0
+    IL_0013:  ldloc.2
+    IL_0014:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+    IL_0019:  call       class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 class TestModule/MyOptionWhichCannotHaveNullInTheInside`1::NewMyNotNullSome(!0)
+    IL_001e:  ret
+  } 
+
+  .method public static valuetype TestModule/MyStructOption`1 
+          mapStructContents(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f,
+                                 valuetype TestModule/MyStructOption`1 myOpt) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+    .param type a 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type b 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    .param [2]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    
+    .maxstack  7
+    .locals init (valuetype TestModule/MyStructOption`1 V_0,
+             !!a V_1,
+             string V_2,
+             string V_3,
+             class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> V_4)
+    IL_0000:  ldarg.1
+    IL_0001:  stloc.0
+    IL_0002:  ldloca.s   V_0
+    IL_0004:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
+    IL_0009:  ldc.i4.1
+    IL_000a:  bne.un.s   IL_000e
+
+    IL_000c:  br.s       IL_0014
+
+    IL_000e:  call       valuetype TestModule/MyStructOption`1 valuetype TestModule/MyStructOption`1::get_MyStructNone()
+    IL_0013:  ret
+
+    IL_0014:  ldloca.s   V_0
+    IL_0016:  ldfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
+    IL_001b:  stloc.1
+    IL_001c:  ldloca.s   V_0
+    IL_001e:  ldfld      string valuetype TestModule/MyStructOption`1::_notNullField2
+    IL_0023:  stloc.2
+    IL_0024:  ldloca.s   V_0
+    IL_0026:  ldfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
+    IL_002b:  stloc.3
+    IL_002c:  ldloca.s   V_0
+    IL_002e:  ldfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
+    IL_0033:  stloc.s    V_4
+    IL_0035:  ldloc.s    V_4
+    IL_0037:  ldloc.2
+    IL_0038:  ldloc.3
+    IL_0039:  ldarg.0
+    IL_003a:  ldloc.1
+    IL_003b:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+    IL_0040:  call       valuetype TestModule/MyStructOption`1 valuetype TestModule/MyStructOption`1::NewMyStructSome(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>,
+                                                                                                                               string,
+                                                                                                                               string,
+                                                                                                                               !0)
+    IL_0045:  ret
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$TestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs
new file mode 100644
index 00000000000..fc9425ee4e2
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs
@@ -0,0 +1,162 @@
+// Copyright (c) Microsoft Corporation.  All Rights Reserved.  See License.txt in the project root for license information.
+
+module EmittedIL.NullnessMetadata
+
+open Xunit
+open FSharp.Test
+open FSharp.Test.Compiler
+
+type Optimize = Optimize | DoNotOptimize
+
+let verifyCompilation (o:Optimize) compilation =
+    compilation
+    |> withLangVersionPreview
+    |> withOptions ["--checknulls"]
+    |> (match o with | Optimize -> withOptimize | DoNotOptimize -> withNoOptimize)
+    |> withNoDebug
+    |> withNoInterfaceData
+    |> withNoOptimizationData
+    |> asLibrary        
+    |> verifyILBaseline
+
+[]
+let ``Nullable attr for module bindings`` compilation =  
+    compilation
+    |> verifyCompilation DoNotOptimize
+
+[]
+let ``Nullable attr for module functions`` compilation =  
+    compilation
+    |> verifyCompilation DoNotOptimize
+
+[]
+let ``Nullable attr for module functions optimize`` compilation =  
+    compilation
+    |> verifyCompilation Optimize
+
+[]
+let ``Nullable attr for curriedFunc optimize`` compilation =  
+    compilation
+    |> verifyCompilation Optimize
+
+[]
+let ``Nullable attr for anon records`` compilation =  
+    compilation
+    |> verifyCompilation DoNotOptimize
+
+[]
+let ``Nullable attr for records`` compilation =  
+    compilation
+    |> verifyCompilation DoNotOptimize
+
+[]
+let ``Nullable attr for ref DUs`` compilation =  
+    compilation
+    |> verifyCompilation DoNotOptimize
+
+[]
+let ``Nullable attr for struct DUs`` compilation =  
+    compilation
+    |> verifyCompilation DoNotOptimize
+
+[]
+let ``Nullable attr for custom type`` compilation =  
+    compilation
+    |> verifyCompilation DoNotOptimize
+
+[]
+let ``Nullable attr for Option clones`` compilation =  
+    compilation
+    |> verifyCompilation DoNotOptimize
+
+
+module Interop  =
+    open System.IO
+
+    let fsharpLibCreator = 
+        FSharp 
+        >> asLibrary 
+        >> withLangVersionPreview 
+        >> withName "MyFSharpLib" 
+        >> withOptions ["--checknulls"]
+
+    let csharpLibCompile fsLibReference = 
+        CSharp 
+        >> withReferences [fsLibReference] 
+        >> withCSharpLanguageVersion CSharpLanguageVersion.Preview
+        >> asLibrary
+        >> withName "CsharpAppConsumingNullness"
+        >> compile
+
+    let FsharpFromFile filename = 
+        Path.Combine(__SOURCE_DIRECTORY__, filename)
+        |> File.ReadAllText
+        |> fsharpLibCreator
+
+    []
+    let ``Csharp understands Fsharp-produced struct unions via IsXXX flow analysis`` () = 
+        let csharpCode = """
+#nullable enable
+public class C {
+    public void M() {
+        var data = MyTestModule.MyStructDU.A;
+        if(data.IsA){
+            string thisMustWarn = data.nonNullableString;
+            string? thisIsOk = data.nonNullableString;
+            string? thisIsAlsoOk = data.nullableString;
+            System.Console.Write(thisMustWarn + thisIsOk + thisIsAlsoOk);
+        } else if(data.IsB){
+            string thisMustBeOK = data.nonNullableString;
+            System.Console.Write(thisMustBeOK.Length);
+        } else if (data.IsC){
+            string evenThoughItIsC_ThisMustStillFailBecauseFieldIsNullable = data.nullableString;
+            System.Console.Write(evenThoughItIsC_ThisMustStillFailBecauseFieldIsNullable.Length);
+        }
+
+        var thisCreationIsBad = MyTestModule.MyStructDU.NewB(null);
+        var thisCreationIsFine = MyTestModule.MyStructDU.NewC(null);
+
+        System.Console.Write(thisCreationIsBad.ToString() + thisCreationIsFine.ToString() );
+    }
+}"""
+        csharpCode
+        |> csharpLibCompile (FsharpFromFile "StructDU.fs")       
+        |> withDiagnostics [
+                    Warning 8600, Line 6, Col 35, Line 6, Col 57, "Converting null literal or possible null value to non-nullable type."
+                    Warning 8600, Line 14, Col 78, Line 14, Col 97, "Converting null literal or possible null value to non-nullable type."
+                    Warning 8602, Line 15, Col 34, Line 15, Col 89, "Dereference of a possibly null reference."
+                    Warning 8625, Line 18, Col 62, Line 18, Col 66, "Cannot convert null literal to non-nullable reference type."]
+
+    []
+    let ``Csharp code understands Fsharp-produced generics`` () = 
+        let fsharpcode = """
+module MyFSharpLib
+let stringTupleInOut(x:struct(string * string|null)) = x """
+        let fsLib = fsharpLibCreator fsharpcode
+        let csharpCode = """
+#nullable enable
+public class C {
+    public void M() {
+        string? nullString = null;
+        MyFSharpLib.stringTupleInOut(("a good string here",nullString));
+    }
+}"""
+        csharpCode
+        |> csharpLibCompile fsLib       
+        |> withDiagnostics []
+
+    []
+    let ``Csharp code can work with annotated FSharp module`` () =
+        Path.Combine(__SOURCE_DIRECTORY__,"CsharpConsumer.cs")
+        |> File.ReadAllText
+        |> csharpLibCompile (FsharpFromFile "ModuleLevelFunctions.fs")
+        |> shouldFail
+        |> withDiagnostics [
+                    Error 29, Line 28, Col 20, Line 28, Col 61, "Cannot implicitly convert type 'int' to 'string'"
+                    Warning 8625, Line 12, Col 74, Line 12, Col 78, "Cannot convert null literal to non-nullable reference type."
+                    Warning 8604, Line 14, Col 88, Line 14, Col 113, "Possible null reference argument for parameter 'x' in 'string MyTestModule.nonNullableInputOutputFunc(string x)'."
+                    Warning 8620, Line 19, Col 88, Line 19, Col 101, "Argument of type '(string?, string?, int, int, int, int)' cannot be used for parameter 'x' of type '(string, string?, int, int, int, int)' in '(string, string?, int, int, int, int) MyTestModule.genericValueTypeTest((string, string?, int, int, int, int) x)' due to differences in the nullability of reference types."
+                    Warning 8604, Line 21, Col 84, Line 21, Col 114, "Possible null reference argument for parameter 'x' in 'string MyTestModule.nonNullableInputOutputFunc(string x)'."
+                    Warning 8604, Line 24, Col 60, Line 24, Col 70, "Possible null reference argument for parameter 'x_0' in 'Tuple MyTestModule.genericRefTypeTest(string x_0, string? x_1, int x_2, int x_3, int x_4, int x_5)'."
+                    Warning 8604, Line 25, Col 45, Line 25, Col 59, "Possible null reference argument for parameter 'x_0' in 'Tuple MyTestModule.genericRefTypeTest(string x_0, string? x_1, int x_2, int x_3, int x_4, int x_5)'."
+                    Warning 8625, Line 28, Col 51, Line 28, Col 55, "Cannot convert null literal to non-nullable reference type."]
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs
new file mode 100644
index 00000000000..2a2c7a09b7e
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs
@@ -0,0 +1,25 @@
+module MyTestModule
+
+let maybeString : string | null = null
+
+[]
+type MyRecord<'X,'Y,'Z when 'Y:null and 'Z:not null> = 
+    {
+        JustInt : int
+        NullInt : System.Nullable
+        JustString : string
+        NullableString : string | null
+        GenericNormalField : 'X
+        GenericNullableField : 'Y
+        GenericNotNullField : 'Z }
+
+let createAnInstance () =
+    {
+        JustInt = 42
+        NullInt = System.Nullable.op_Implicit(42)
+        JustString = ""
+        NullableString = null
+        GenericNormalField = 42
+        GenericNullableField = maybeString
+        GenericNotNullField = ""}
+    
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.net472.bsl
new file mode 100644
index 00000000000..ce45234c3e9
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.net472.bsl
@@ -0,0 +1,460 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .class auto ansi serializable sealed nested public beforefieldinit MyRecord`3
+         extends [runtime]System.Object
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type X 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    .param type Y 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .param type Z 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .field assembly int32 JustInt@
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .field assembly valuetype [runtime]System.Nullable`1 NullInt@
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .field assembly string JustString@
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .field assembly string NullableString@
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .field assembly !X GenericNormalField@
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .field assembly !Y GenericNullableField@
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .field assembly !Z GenericNotNullField@
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .method public hidebysig specialname 
+            instance int32  get_JustInt() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      int32 class MyTestModule/MyRecord`3::JustInt@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance valuetype [runtime]System.Nullable`1 
+            get_NullInt() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      valuetype [runtime]System.Nullable`1 class MyTestModule/MyRecord`3::NullInt@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance string  get_JustString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string class MyTestModule/MyRecord`3::JustString@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance string  get_NullableString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string class MyTestModule/MyRecord`3::NullableString@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance !X  get_GenericNormalField() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      !0 class MyTestModule/MyRecord`3::GenericNormalField@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance !Y  get_GenericNullableField() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      !1 class MyTestModule/MyRecord`3::GenericNullableField@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance !Z  get_GenericNotNullField() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      !2 class MyTestModule/MyRecord`3::GenericNotNullField@
+      IL_0006:  ret
+    } 
+
+    .method public specialname rtspecialname 
+            instance void  .ctor(int32 justInt,
+                                 valuetype [runtime]System.Nullable`1 nullInt,
+                                 string justString,
+                                 string nullableString,
+                                 !X genericNormalField,
+                                 !Y genericNullableField,
+                                 !Z genericNotNullField) cil managed
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                              class [runtime]System.Type) = ( 01 00 60 06 00 00 17 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                               75 6C 65 2B 4D 79 52 65 63 6F 72 64 60 33 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void [runtime]System.Object::.ctor()
+      IL_0006:  ldarg.0
+      IL_0007:  ldarg.1
+      IL_0008:  stfld      int32 class MyTestModule/MyRecord`3::JustInt@
+      IL_000d:  ldarg.0
+      IL_000e:  ldarg.2
+      IL_000f:  stfld      valuetype [runtime]System.Nullable`1 class MyTestModule/MyRecord`3::NullInt@
+      IL_0014:  ldarg.0
+      IL_0015:  ldarg.3
+      IL_0016:  stfld      string class MyTestModule/MyRecord`3::JustString@
+      IL_001b:  ldarg.0
+      IL_001c:  ldarg.s    nullableString
+      IL_001e:  stfld      string class MyTestModule/MyRecord`3::NullableString@
+      IL_0023:  ldarg.0
+      IL_0024:  ldarg.s    genericNormalField
+      IL_0026:  stfld      !0 class MyTestModule/MyRecord`3::GenericNormalField@
+      IL_002b:  ldarg.0
+      IL_002c:  ldarg.s    genericNullableField
+      IL_002e:  stfld      !1 class MyTestModule/MyRecord`3::GenericNullableField@
+      IL_0033:  ldarg.0
+      IL_0034:  ldarg.s    genericNotNullField
+      IL_0036:  stfld      !2 class MyTestModule/MyRecord`3::GenericNotNullField@
+      IL_003b:  ret
+    } 
+
+    .method public strict virtual instance string 
+            ToString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class MyTestModule/MyRecord`3>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_0015:  ret
+    } 
+
+    .property instance int32 JustInt()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) 
+      .get instance int32 MyTestModule/MyRecord`3::get_JustInt()
+    } 
+    .property instance valuetype [runtime]System.Nullable`1
+            NullInt()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) 
+      .get instance valuetype [runtime]System.Nullable`1 MyTestModule/MyRecord`3::get_NullInt()
+    } 
+    .property instance string JustString()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) 
+      .get instance string MyTestModule/MyRecord`3::get_JustString()
+    } 
+    .property instance string NullableString()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 04 00 00 00 03 00 00 00 00 00 ) 
+      .get instance string MyTestModule/MyRecord`3::get_NullableString()
+    } 
+    .property instance !X GenericNormalField()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 04 00 00 00 04 00 00 00 00 00 ) 
+      .get instance !X MyTestModule/MyRecord`3::get_GenericNormalField()
+    } 
+    .property instance !Y GenericNullableField()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 04 00 00 00 05 00 00 00 00 00 ) 
+      .get instance !Y MyTestModule/MyRecord`3::get_GenericNullableField()
+    } 
+    .property instance !Z GenericNotNullField()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 04 00 00 00 06 00 00 00 00 00 ) 
+      .get instance !Z MyTestModule/MyRecord`3::get_GenericNotNullField()
+    } 
+  } 
+
+  .method public specialname static string 
+          get_maybeString() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldnull
+    IL_0001:  ret
+  } 
+
+  .method public static class MyTestModule/MyRecord`3 
+          createAnInstance() cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 01 00 00 ) 
+    
+    .maxstack  9
+    IL_0000:  ldc.i4.s   42
+    IL_0002:  ldc.i4.s   42
+    IL_0004:  call       valuetype [runtime]System.Nullable`1 valuetype [runtime]System.Nullable`1::op_Implicit(!0)
+    IL_0009:  ldstr      ""
+    IL_000e:  ldnull
+    IL_000f:  ldc.i4.s   42
+    IL_0011:  call       string MyTestModule::get_maybeString()
+    IL_0016:  ldstr      ""
+    IL_001b:  newobj     instance void class MyTestModule/MyRecord`3::.ctor(int32,
+                                                                                                 valuetype [runtime]System.Nullable`1,
+                                                                                                 string,
+                                                                                                 string,
+                                                                                                 !0,
+                                                                                                 !1,
+                                                                                                 !2)
+    IL_0020:  ret
+  } 
+
+  .property string maybeString()
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .get string MyTestModule::get_maybeString()
+  } 
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi serializable sealed System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes
+       extends [runtime]System.Enum
+{
+  .custom instance void [runtime]System.FlagsAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public specialname rtspecialname int32 value__
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes All = int32(0xFFFFFFFF)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes None = int32(0x00000000)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicParameterlessConstructor = int32(0x00000001)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicConstructors = int32(0x00000003)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicConstructors = int32(0x00000004)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicMethods = int32(0x00000008)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicMethods = int32(0x00000010)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicFields = int32(0x00000020)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicFields = int32(0x00000040)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicNestedTypes = int32(0x00000080)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicNestedTypes = int32(0x00000100)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicProperties = int32(0x00000200)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicProperties = int32(0x00000400)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicEvents = int32(0x00000800)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicEvents = int32(0x00001000)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes Interfaces = int32(0x00002000)
+} 
+
+.class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute
+       extends [runtime]System.Attribute
+{
+  .field private valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field private class [runtime]System.Type Type@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType,
+                               class [runtime]System.Type Type) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::MemberType@
+    IL_000d:  ldarg.0
+    IL_000e:  ldarg.2
+    IL_000f:  stfld      class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::Type@
+    IL_0014:  ret
+  } 
+
+  .method public hidebysig specialname instance class [runtime]System.Type 
+          get_Type() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::Type@
+    IL_0006:  ret
+  } 
+
+  .method public hidebysig specialname instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes 
+          get_MemberType() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::MemberType@
+    IL_0006:  ret
+  } 
+
+  .property instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes
+          MemberType()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::get_MemberType()
+  } 
+  .property instance class [runtime]System.Type
+          Type()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::get_Type()
+  } 
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.netcore.bsl
new file mode 100644
index 00000000000..b29b5667144
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.netcore.bsl
@@ -0,0 +1,367 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .class auto ansi serializable sealed nested public beforefieldinit MyRecord`3
+         extends [runtime]System.Object
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type X 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    .param type Y 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .param type Z 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .field assembly int32 JustInt@
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .field assembly valuetype [runtime]System.Nullable`1 NullInt@
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .field assembly string JustString@
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .field assembly string NullableString@
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .field assembly !X GenericNormalField@
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .field assembly !Y GenericNullableField@
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .field assembly !Z GenericNotNullField@
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .method public hidebysig specialname 
+            instance int32  get_JustInt() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      int32 class MyTestModule/MyRecord`3::JustInt@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance valuetype [runtime]System.Nullable`1 
+            get_NullInt() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      valuetype [runtime]System.Nullable`1 class MyTestModule/MyRecord`3::NullInt@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance string  get_JustString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string class MyTestModule/MyRecord`3::JustString@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance string  get_NullableString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string class MyTestModule/MyRecord`3::NullableString@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance !X  get_GenericNormalField() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      !0 class MyTestModule/MyRecord`3::GenericNormalField@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance !Y  get_GenericNullableField() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      !1 class MyTestModule/MyRecord`3::GenericNullableField@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance !Z  get_GenericNotNullField() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      !2 class MyTestModule/MyRecord`3::GenericNotNullField@
+      IL_0006:  ret
+    } 
+
+    .method public specialname rtspecialname 
+            instance void  .ctor(int32 justInt,
+                                 valuetype [runtime]System.Nullable`1 nullInt,
+                                 string justString,
+                                 string nullableString,
+                                 !X genericNormalField,
+                                 !Y genericNullableField,
+                                 !Z genericNotNullField) cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                              class [runtime]System.Type) = ( 01 00 60 06 00 00 17 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                                     75 6C 65 2B 4D 79 52 65 63 6F 72 64 60 33 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void [runtime]System.Object::.ctor()
+      IL_0006:  ldarg.0
+      IL_0007:  ldarg.1
+      IL_0008:  stfld      int32 class MyTestModule/MyRecord`3::JustInt@
+      IL_000d:  ldarg.0
+      IL_000e:  ldarg.2
+      IL_000f:  stfld      valuetype [runtime]System.Nullable`1 class MyTestModule/MyRecord`3::NullInt@
+      IL_0014:  ldarg.0
+      IL_0015:  ldarg.3
+      IL_0016:  stfld      string class MyTestModule/MyRecord`3::JustString@
+      IL_001b:  ldarg.0
+      IL_001c:  ldarg.s    nullableString
+      IL_001e:  stfld      string class MyTestModule/MyRecord`3::NullableString@
+      IL_0023:  ldarg.0
+      IL_0024:  ldarg.s    genericNormalField
+      IL_0026:  stfld      !0 class MyTestModule/MyRecord`3::GenericNormalField@
+      IL_002b:  ldarg.0
+      IL_002c:  ldarg.s    genericNullableField
+      IL_002e:  stfld      !1 class MyTestModule/MyRecord`3::GenericNullableField@
+      IL_0033:  ldarg.0
+      IL_0034:  ldarg.s    genericNotNullField
+      IL_0036:  stfld      !2 class MyTestModule/MyRecord`3::GenericNotNullField@
+      IL_003b:  ret
+    } 
+
+    .method public strict virtual instance string 
+            ToString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class MyTestModule/MyRecord`3>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_0015:  ret
+    } 
+
+    .property instance int32 JustInt()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) 
+      .get instance int32 MyTestModule/MyRecord`3::get_JustInt()
+    } 
+    .property instance valuetype [runtime]System.Nullable`1
+            NullInt()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) 
+      .get instance valuetype [runtime]System.Nullable`1 MyTestModule/MyRecord`3::get_NullInt()
+    } 
+    .property instance string JustString()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) 
+      .get instance string MyTestModule/MyRecord`3::get_JustString()
+    } 
+    .property instance string NullableString()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 04 00 00 00 03 00 00 00 00 00 ) 
+      .get instance string MyTestModule/MyRecord`3::get_NullableString()
+    } 
+    .property instance !X GenericNormalField()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 04 00 00 00 04 00 00 00 00 00 ) 
+      .get instance !X MyTestModule/MyRecord`3::get_GenericNormalField()
+    } 
+    .property instance !Y GenericNullableField()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 04 00 00 00 05 00 00 00 00 00 ) 
+      .get instance !Y MyTestModule/MyRecord`3::get_GenericNullableField()
+    } 
+    .property instance !Z GenericNotNullField()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 04 00 00 00 06 00 00 00 00 00 ) 
+      .get instance !Z MyTestModule/MyRecord`3::get_GenericNotNullField()
+    } 
+  } 
+
+  .method public specialname static string 
+          get_maybeString() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldnull
+    IL_0001:  ret
+  } 
+
+  .method public static class MyTestModule/MyRecord`3 
+          createAnInstance() cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 01 00 00 ) 
+    
+    .maxstack  9
+    IL_0000:  ldc.i4.s   42
+    IL_0002:  ldc.i4.s   42
+    IL_0004:  call       valuetype [runtime]System.Nullable`1 valuetype [runtime]System.Nullable`1::op_Implicit(!0)
+    IL_0009:  ldstr      ""
+    IL_000e:  ldnull
+    IL_000f:  ldc.i4.s   42
+    IL_0011:  call       string MyTestModule::get_maybeString()
+    IL_0016:  ldstr      ""
+    IL_001b:  newobj     instance void class MyTestModule/MyRecord`3::.ctor(int32,
+                                                                                                 valuetype [runtime]System.Nullable`1,
+                                                                                                 string,
+                                                                                                 string,
+                                                                                                 !0,
+                                                                                                 !1,
+                                                                                                 !2)
+    IL_0020:  ret
+  } 
+
+  .property string maybeString()
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .get string MyTestModule::get_maybeString()
+  } 
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs
new file mode 100644
index 00000000000..b4d87d8293d
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs
@@ -0,0 +1,18 @@
+module MyTestModule
+
+[]
+type MyDu = 
+    | JustLabel
+    | JustInt of int
+    | MaybeString of (string | null)
+
+let giveMeLabel () = JustLabel
+
+let createMaybeString (innerValue) = MaybeString innerValue
+
+let processNullableDu (x : (MyDu | null)) : string | null =
+    match x with
+    | null -> null
+    | JustLabel -> null
+    | JustInt x -> string x
+    | MaybeString x -> x
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.net472.bsl
new file mode 100644
index 00000000000..d84066219d8
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.net472.bsl
@@ -0,0 +1,772 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly extern netstandard
+{
+  .publickeytoken = (CC 7B 13 FF CD 2D DD 51 )                         
+  .ver 2:0:0:0
+}
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .class abstract auto autochar serializable nested public beforefieldinit MyDu
+         extends [runtime]System.Object
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                   61 79 28 29 2C 6E 71 7D 00 00 )                   
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .class abstract auto ansi sealed nested public Tags
+           extends [runtime]System.Object
+    {
+      .field public static literal int32 JustLabel = int32(0x00000000)
+      .field public static literal int32 JustInt = int32(0x00000001)
+      .field public static literal int32 MaybeString = int32(0x00000002)
+    } 
+
+    .class auto ansi serializable nested assembly beforefieldinit specialname _JustLabel
+           extends MyTestModule/MyDu
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerTypeProxyAttribute::.ctor(class [runtime]System.Type) = ( 01 00 2B 4D 79 54 65 73 74 4D 6F 64 75 6C 65 2B   
+                                                                                                                            4D 79 44 75 2B 5F 4A 75 73 74 4C 61 62 65 6C 40   
+                                                                                                                            44 65 62 75 67 54 79 70 65 50 72 6F 78 79 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                     61 79 28 29 2C 6E 71 7D 00 00 )                   
+      .method assembly specialname rtspecialname 
+              instance void  .ctor() cil managed
+      {
+        .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                class [runtime]System.Type) = ( 01 00 60 06 00 00 11 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                 75 6C 65 2B 4D 79 44 75 00 00 )                   
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  call       instance void MyTestModule/MyDu::.ctor()
+        IL_0006:  ret
+      } 
+
+    } 
+
+    .class auto ansi serializable nested public beforefieldinit specialname JustInt
+           extends MyTestModule/MyDu
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerTypeProxyAttribute::.ctor(class [runtime]System.Type) = ( 01 00 28 4D 79 54 65 73 74 4D 6F 64 75 6C 65 2B   
+                                                                                                                            4D 79 44 75 2B 4A 75 73 74 49 6E 74 40 44 65 62   
+                                                                                                                            75 67 54 79 70 65 50 72 6F 78 79 00 00 )          
+      .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                     61 79 28 29 2C 6E 71 7D 00 00 )                   
+      .field assembly initonly int32 item
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .method assembly specialname rtspecialname 
+              instance void  .ctor(int32 item) cil managed
+      {
+        .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                class [runtime]System.Type) = ( 01 00 60 06 00 00 11 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                 75 6C 65 2B 4D 79 44 75 00 00 )                   
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  call       instance void MyTestModule/MyDu::.ctor()
+        IL_0006:  ldarg.0
+        IL_0007:  ldarg.1
+        IL_0008:  stfld      int32 MyTestModule/MyDu/JustInt::item
+        IL_000d:  ret
+      } 
+
+      .method public hidebysig instance int32 
+              get_Item() cil managed
+      {
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  ldfld      int32 MyTestModule/MyDu/JustInt::item
+        IL_0006:  ret
+      } 
+
+      .property instance int32 Item()
+      {
+        .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                    int32,
+                                                                                                    int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        .get instance int32 MyTestModule/MyDu/JustInt::get_Item()
+      } 
+    } 
+
+    .class auto ansi serializable nested public beforefieldinit specialname MaybeString
+           extends MyTestModule/MyDu
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerTypeProxyAttribute::.ctor(class [runtime]System.Type) = ( 01 00 2C 4D 79 54 65 73 74 4D 6F 64 75 6C 65 2B   
+                                                                                                                            4D 79 44 75 2B 4D 61 79 62 65 53 74 72 69 6E 67   
+                                                                                                                            40 44 65 62 75 67 54 79 70 65 50 72 6F 78 79 00   
+                                                                                                                            00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                     61 79 28 29 2C 6E 71 7D 00 00 )                   
+      .field assembly initonly string item
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .method assembly specialname rtspecialname 
+              instance void  .ctor(string item) cil managed
+      {
+        .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                class [runtime]System.Type) = ( 01 00 60 06 00 00 11 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                 75 6C 65 2B 4D 79 44 75 00 00 )                   
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  call       instance void MyTestModule/MyDu::.ctor()
+        IL_0006:  ldarg.0
+        IL_0007:  ldarg.1
+        IL_0008:  stfld      string MyTestModule/MyDu/MaybeString::item
+        IL_000d:  ret
+      } 
+
+      .method public hidebysig instance string 
+              get_Item() cil managed
+      {
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        .param [0]
+        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  ldfld      string MyTestModule/MyDu/MaybeString::item
+        IL_0006:  ret
+      } 
+
+      .property instance string Item()
+      {
+        .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                    int32,
+                                                                                                    int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 00 00 00 00 ) 
+        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        .get instance string MyTestModule/MyDu/MaybeString::get_Item()
+      } 
+    } 
+
+    .class auto ansi nested assembly beforefieldinit specialname _JustLabel@DebugTypeProxy
+           extends [runtime]System.Object
+    {
+      .field assembly class MyTestModule/MyDu/_JustLabel _obj
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .method public specialname rtspecialname 
+              instance void  .ctor(class MyTestModule/MyDu/_JustLabel obj) cil managed
+      {
+        .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                class [runtime]System.Type) = ( 01 00 60 06 00 00 11 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                 75 6C 65 2B 4D 79 44 75 00 00 )                   
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  call       instance void [runtime]System.Object::.ctor()
+        IL_0006:  ldarg.0
+        IL_0007:  ldarg.1
+        IL_0008:  stfld      class MyTestModule/MyDu/_JustLabel MyTestModule/MyDu/_JustLabel@DebugTypeProxy::_obj
+        IL_000d:  ret
+      } 
+
+    } 
+
+    .class auto ansi nested assembly beforefieldinit specialname JustInt@DebugTypeProxy
+           extends [runtime]System.Object
+    {
+      .field assembly class MyTestModule/MyDu/JustInt _obj
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .method public specialname rtspecialname 
+              instance void  .ctor(class MyTestModule/MyDu/JustInt obj) cil managed
+      {
+        .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                class [runtime]System.Type) = ( 01 00 60 06 00 00 11 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                 75 6C 65 2B 4D 79 44 75 00 00 )                   
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  call       instance void [runtime]System.Object::.ctor()
+        IL_0006:  ldarg.0
+        IL_0007:  ldarg.1
+        IL_0008:  stfld      class MyTestModule/MyDu/JustInt MyTestModule/MyDu/JustInt@DebugTypeProxy::_obj
+        IL_000d:  ret
+      } 
+
+      .method public hidebysig instance int32 
+              get_Item() cil managed
+      {
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  ldfld      class MyTestModule/MyDu/JustInt MyTestModule/MyDu/JustInt@DebugTypeProxy::_obj
+        IL_0006:  ldfld      int32 MyTestModule/MyDu/JustInt::item
+        IL_000b:  ret
+      } 
+
+      .property instance int32 Item()
+      {
+        .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                    int32,
+                                                                                                    int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        .get instance int32 MyTestModule/MyDu/JustInt@DebugTypeProxy::get_Item()
+      } 
+    } 
+
+    .class auto ansi nested assembly beforefieldinit specialname MaybeString@DebugTypeProxy
+           extends [runtime]System.Object
+    {
+      .field assembly class MyTestModule/MyDu/MaybeString _obj
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .method public specialname rtspecialname 
+              instance void  .ctor(class MyTestModule/MyDu/MaybeString obj) cil managed
+      {
+        .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                class [runtime]System.Type) = ( 01 00 60 06 00 00 11 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                 75 6C 65 2B 4D 79 44 75 00 00 )                   
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  call       instance void [runtime]System.Object::.ctor()
+        IL_0006:  ldarg.0
+        IL_0007:  ldarg.1
+        IL_0008:  stfld      class MyTestModule/MyDu/MaybeString MyTestModule/MyDu/MaybeString@DebugTypeProxy::_obj
+        IL_000d:  ret
+      } 
+
+      .method public hidebysig instance string 
+              get_Item() cil managed
+      {
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  ldfld      class MyTestModule/MyDu/MaybeString MyTestModule/MyDu/MaybeString@DebugTypeProxy::_obj
+        IL_0006:  ldfld      string MyTestModule/MyDu/MaybeString::item
+        IL_000b:  ret
+      } 
+
+      .property instance string Item()
+      {
+        .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                    int32,
+                                                                                                    int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 00 00 00 00 ) 
+        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        .get instance string MyTestModule/MyDu/MaybeString@DebugTypeProxy::get_Item()
+      } 
+    } 
+
+    .field static assembly initonly class MyTestModule/MyDu _unique_JustLabel
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .method private specialname rtspecialname static 
+            void  .cctor() cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  newobj     instance void MyTestModule/MyDu/_JustLabel::.ctor()
+      IL_0005:  stsfld     class MyTestModule/MyDu MyTestModule/MyDu::_unique_JustLabel
+      IL_000a:  ret
+    } 
+
+    .method assembly specialname rtspecialname 
+            instance void  .ctor() cil managed
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                              class [runtime]System.Type) = ( 01 00 E0 07 00 00 11 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                               75 6C 65 2B 4D 79 44 75 00 00 )                   
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void [runtime]System.Object::.ctor()
+      IL_0006:  ret
+    } 
+
+    .method public static class MyTestModule/MyDu 
+            get_JustLabel() cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldsfld     class MyTestModule/MyDu MyTestModule/MyDu::_unique_JustLabel
+      IL_0005:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsJustLabel() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  isinst     MyTestModule/MyDu/_JustLabel
+      IL_0006:  ldnull
+      IL_0007:  cgt.un
+      IL_0009:  ret
+    } 
+
+    .method public static class MyTestModule/MyDu 
+            NewJustInt(int32 item) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  newobj     instance void MyTestModule/MyDu/JustInt::.ctor(int32)
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsJustInt() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  isinst     MyTestModule/MyDu/JustInt
+      IL_0006:  ldnull
+      IL_0007:  cgt.un
+      IL_0009:  ret
+    } 
+
+    .method public static class MyTestModule/MyDu 
+            NewMaybeString(string item) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 02 00 00 00 00 00 ) 
+      .param [1]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  newobj     instance void MyTestModule/MyDu/MaybeString::.ctor(string)
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsMaybeString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  isinst     MyTestModule/MyDu/MaybeString
+      IL_0006:  ldnull
+      IL_0007:  cgt.un
+      IL_0009:  ret
+    } 
+
+    .method public hidebysig instance int32 
+            get_Tag() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  isinst     MyTestModule/MyDu/MaybeString
+      IL_0006:  brfalse.s  IL_000b
+
+      IL_0008:  ldc.i4.2
+      IL_0009:  br.s       IL_0017
+
+      IL_000b:  ldarg.0
+      IL_000c:  isinst     MyTestModule/MyDu/JustInt
+      IL_0011:  brfalse.s  IL_0016
+
+      IL_0013:  ldc.i4.1
+      IL_0014:  br.s       IL_0017
+
+      IL_0016:  ldc.i4.0
+      IL_0017:  ret
+    } 
+
+    .method assembly hidebysig specialname 
+            instance object  __DebugDisplay() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+0.8A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+      IL_0015:  ret
+    } 
+
+    .method public strict virtual instance string 
+            ToString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class MyTestModule/MyDu>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+      IL_0015:  ret
+    } 
+
+    .property instance int32 Tag()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance int32 MyTestModule/MyDu::get_Tag()
+    } 
+    .property class MyTestModule/MyDu JustLabel()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get class MyTestModule/MyDu MyTestModule/MyDu::get_JustLabel()
+    } 
+    .property instance bool IsJustLabel()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool MyTestModule/MyDu::get_IsJustLabel()
+    } 
+    .property instance bool IsJustInt()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool MyTestModule/MyDu::get_IsJustInt()
+    } 
+    .property instance bool IsMaybeString()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool MyTestModule/MyDu::get_IsMaybeString()
+    } 
+  } 
+
+  .method public static class MyTestModule/MyDu 
+          giveMeLabel() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  call       class MyTestModule/MyDu MyTestModule/MyDu::get_JustLabel()
+    IL_0005:  ret
+  } 
+
+  .method public static class MyTestModule/MyDu 
+          createMaybeString(string innerValue) cil managed
+  {
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       class MyTestModule/MyDu MyTestModule/MyDu::NewMaybeString(string)
+    IL_0006:  ret
+  } 
+
+  .method public static string  processNullableDu(class MyTestModule/MyDu x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  5
+    .locals init (class MyTestModule/MyDu V_0,
+             class MyTestModule/MyDu V_1,
+             class MyTestModule/MyDu/JustInt V_2,
+             int32 V_3,
+             int32 V_4,
+             class MyTestModule/MyDu/MaybeString V_5,
+             string V_6)
+    IL_0000:  ldarg.0
+    IL_0001:  stloc.0
+    IL_0002:  ldloc.0
+    IL_0003:  brfalse.s  IL_0019
+
+    IL_0005:  ldloc.0
+    IL_0006:  stloc.1
+    IL_0007:  ldloc.1
+    IL_0008:  isinst     MyTestModule/MyDu/JustInt
+    IL_000d:  brtrue.s   IL_001d
+
+    IL_000f:  ldloc.1
+    IL_0010:  isinst     MyTestModule/MyDu/MaybeString
+    IL_0015:  brtrue.s   IL_0048
+
+    IL_0017:  br.s       IL_001b
+
+    IL_0019:  ldnull
+    IL_001a:  ret
+
+    IL_001b:  ldnull
+    IL_001c:  ret
+
+    IL_001d:  ldloc.0
+    IL_001e:  castclass  MyTestModule/MyDu/JustInt
+    IL_0023:  stloc.2
+    IL_0024:  ldloc.2
+    IL_0025:  ldfld      int32 MyTestModule/MyDu/JustInt::item
+    IL_002a:  stloc.3
+    IL_002b:  ldloc.3
+    IL_002c:  stloc.s    V_4
+    IL_002e:  ldloc.s    V_4
+    IL_0030:  box        [runtime]System.Int32
+    IL_0035:  unbox.any  [runtime]System.IFormattable
+    IL_003a:  ldnull
+    IL_003b:  call       class [netstandard]System.Globalization.CultureInfo [netstandard]System.Globalization.CultureInfo::get_InvariantCulture()
+    IL_0040:  tail.
+    IL_0042:  callvirt   instance string [netstandard]System.IFormattable::ToString(string,
+                                                                                    class [netstandard]System.IFormatProvider)
+    IL_0047:  ret
+
+    IL_0048:  ldloc.0
+    IL_0049:  castclass  MyTestModule/MyDu/MaybeString
+    IL_004e:  stloc.s    V_5
+    IL_0050:  ldloc.s    V_5
+    IL_0052:  ldfld      string MyTestModule/MyDu/MaybeString::item
+    IL_0057:  stloc.s    V_6
+    IL_0059:  ldloc.s    V_6
+    IL_005b:  ret
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi serializable sealed System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes
+       extends [runtime]System.Enum
+{
+  .custom instance void [runtime]System.FlagsAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public specialname rtspecialname int32 value__
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes All = int32(0xFFFFFFFF)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes None = int32(0x00000000)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicParameterlessConstructor = int32(0x00000001)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicConstructors = int32(0x00000003)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicConstructors = int32(0x00000004)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicMethods = int32(0x00000008)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicMethods = int32(0x00000010)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicFields = int32(0x00000020)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicFields = int32(0x00000040)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicNestedTypes = int32(0x00000080)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicNestedTypes = int32(0x00000100)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicProperties = int32(0x00000200)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicProperties = int32(0x00000400)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicEvents = int32(0x00000800)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicEvents = int32(0x00001000)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes Interfaces = int32(0x00002000)
+} 
+
+.class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute
+       extends [runtime]System.Attribute
+{
+  .field private valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field private class [runtime]System.Type Type@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType,
+                               class [runtime]System.Type Type) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::MemberType@
+    IL_000d:  ldarg.0
+    IL_000e:  ldarg.2
+    IL_000f:  stfld      class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::Type@
+    IL_0014:  ret
+  } 
+
+  .method public hidebysig specialname instance class [runtime]System.Type 
+          get_Type() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::Type@
+    IL_0006:  ret
+  } 
+
+  .method public hidebysig specialname instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes 
+          get_MemberType() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::MemberType@
+    IL_0006:  ret
+  } 
+
+  .property instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes
+          MemberType()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::get_MemberType()
+  } 
+  .property instance class [runtime]System.Type
+          Type()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::get_Type()
+  } 
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.netcore.bsl
new file mode 100644
index 00000000000..da1235dd5eb
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.netcore.bsl
@@ -0,0 +1,679 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly extern netstandard
+{
+  .publickeytoken = (CC 7B 13 FF CD 2D DD 51 )                         
+  .ver 2:1:0:0
+}
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .class abstract auto autochar serializable nested public beforefieldinit MyDu
+         extends [runtime]System.Object
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                         61 79 28 29 2C 6E 71 7D 00 00 )                   
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .class abstract auto ansi sealed nested public Tags
+           extends [runtime]System.Object
+    {
+      .field public static literal int32 JustLabel = int32(0x00000000)
+      .field public static literal int32 JustInt = int32(0x00000001)
+      .field public static literal int32 MaybeString = int32(0x00000002)
+    } 
+
+    .class auto ansi serializable nested assembly beforefieldinit specialname _JustLabel
+           extends MyTestModule/MyDu
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerTypeProxyAttribute::.ctor(class [runtime]System.Type) = ( 01 00 2B 4D 79 54 65 73 74 4D 6F 64 75 6C 65 2B   
+                                                                                                                                        4D 79 44 75 2B 5F 4A 75 73 74 4C 61 62 65 6C 40   
+                                                                                                                                        44 65 62 75 67 54 79 70 65 50 72 6F 78 79 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                           61 79 28 29 2C 6E 71 7D 00 00 )                   
+      .method assembly specialname rtspecialname 
+              instance void  .ctor() cil managed
+      {
+        .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                                class [runtime]System.Type) = ( 01 00 60 06 00 00 11 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                                       75 6C 65 2B 4D 79 44 75 00 00 )                   
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  call       instance void MyTestModule/MyDu::.ctor()
+        IL_0006:  ret
+      } 
+
+    } 
+
+    .class auto ansi serializable nested public beforefieldinit specialname JustInt
+           extends MyTestModule/MyDu
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerTypeProxyAttribute::.ctor(class [runtime]System.Type) = ( 01 00 28 4D 79 54 65 73 74 4D 6F 64 75 6C 65 2B   
+                                                                                                                                        4D 79 44 75 2B 4A 75 73 74 49 6E 74 40 44 65 62   
+                                                                                                                                        75 67 54 79 70 65 50 72 6F 78 79 00 00 )          
+      .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                           61 79 28 29 2C 6E 71 7D 00 00 )                   
+      .field assembly initonly int32 item
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .method assembly specialname rtspecialname 
+              instance void  .ctor(int32 item) cil managed
+      {
+        .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                                class [runtime]System.Type) = ( 01 00 60 06 00 00 11 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                                       75 6C 65 2B 4D 79 44 75 00 00 )                   
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  call       instance void MyTestModule/MyDu::.ctor()
+        IL_0006:  ldarg.0
+        IL_0007:  ldarg.1
+        IL_0008:  stfld      int32 MyTestModule/MyDu/JustInt::item
+        IL_000d:  ret
+      } 
+
+      .method public hidebysig instance int32 
+              get_Item() cil managed
+      {
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  ldfld      int32 MyTestModule/MyDu/JustInt::item
+        IL_0006:  ret
+      } 
+
+      .property instance int32 Item()
+      {
+        .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                    int32,
+                                                                                                    int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        .get instance int32 MyTestModule/MyDu/JustInt::get_Item()
+      } 
+    } 
+
+    .class auto ansi serializable nested public beforefieldinit specialname MaybeString
+           extends MyTestModule/MyDu
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerTypeProxyAttribute::.ctor(class [runtime]System.Type) = ( 01 00 2C 4D 79 54 65 73 74 4D 6F 64 75 6C 65 2B   
+                                                                                                                                        4D 79 44 75 2B 4D 61 79 62 65 53 74 72 69 6E 67   
+                                                                                                                                        40 44 65 62 75 67 54 79 70 65 50 72 6F 78 79 00   
+                                                                                                                                        00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                           61 79 28 29 2C 6E 71 7D 00 00 )                   
+      .field assembly initonly string item
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .method assembly specialname rtspecialname 
+              instance void  .ctor(string item) cil managed
+      {
+        .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                                class [runtime]System.Type) = ( 01 00 60 06 00 00 11 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                                       75 6C 65 2B 4D 79 44 75 00 00 )                   
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  call       instance void MyTestModule/MyDu::.ctor()
+        IL_0006:  ldarg.0
+        IL_0007:  ldarg.1
+        IL_0008:  stfld      string MyTestModule/MyDu/MaybeString::item
+        IL_000d:  ret
+      } 
+
+      .method public hidebysig instance string 
+              get_Item() cil managed
+      {
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        .param [0]
+        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  ldfld      string MyTestModule/MyDu/MaybeString::item
+        IL_0006:  ret
+      } 
+
+      .property instance string Item()
+      {
+        .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                    int32,
+                                                                                                    int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 00 00 00 00 ) 
+        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        .get instance string MyTestModule/MyDu/MaybeString::get_Item()
+      } 
+    } 
+
+    .class auto ansi nested assembly beforefieldinit specialname _JustLabel@DebugTypeProxy
+           extends [runtime]System.Object
+    {
+      .field assembly class MyTestModule/MyDu/_JustLabel _obj
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .method public specialname rtspecialname 
+              instance void  .ctor(class MyTestModule/MyDu/_JustLabel obj) cil managed
+      {
+        .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                                class [runtime]System.Type) = ( 01 00 60 06 00 00 11 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                                       75 6C 65 2B 4D 79 44 75 00 00 )                   
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  call       instance void [runtime]System.Object::.ctor()
+        IL_0006:  ldarg.0
+        IL_0007:  ldarg.1
+        IL_0008:  stfld      class MyTestModule/MyDu/_JustLabel MyTestModule/MyDu/_JustLabel@DebugTypeProxy::_obj
+        IL_000d:  ret
+      } 
+
+    } 
+
+    .class auto ansi nested assembly beforefieldinit specialname JustInt@DebugTypeProxy
+           extends [runtime]System.Object
+    {
+      .field assembly class MyTestModule/MyDu/JustInt _obj
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .method public specialname rtspecialname 
+              instance void  .ctor(class MyTestModule/MyDu/JustInt obj) cil managed
+      {
+        .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                                class [runtime]System.Type) = ( 01 00 60 06 00 00 11 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                                       75 6C 65 2B 4D 79 44 75 00 00 )                   
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  call       instance void [runtime]System.Object::.ctor()
+        IL_0006:  ldarg.0
+        IL_0007:  ldarg.1
+        IL_0008:  stfld      class MyTestModule/MyDu/JustInt MyTestModule/MyDu/JustInt@DebugTypeProxy::_obj
+        IL_000d:  ret
+      } 
+
+      .method public hidebysig instance int32 
+              get_Item() cil managed
+      {
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  ldfld      class MyTestModule/MyDu/JustInt MyTestModule/MyDu/JustInt@DebugTypeProxy::_obj
+        IL_0006:  ldfld      int32 MyTestModule/MyDu/JustInt::item
+        IL_000b:  ret
+      } 
+
+      .property instance int32 Item()
+      {
+        .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                    int32,
+                                                                                                    int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        .get instance int32 MyTestModule/MyDu/JustInt@DebugTypeProxy::get_Item()
+      } 
+    } 
+
+    .class auto ansi nested assembly beforefieldinit specialname MaybeString@DebugTypeProxy
+           extends [runtime]System.Object
+    {
+      .field assembly class MyTestModule/MyDu/MaybeString _obj
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .method public specialname rtspecialname 
+              instance void  .ctor(class MyTestModule/MyDu/MaybeString obj) cil managed
+      {
+        .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                                class [runtime]System.Type) = ( 01 00 60 06 00 00 11 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                                       75 6C 65 2B 4D 79 44 75 00 00 )                   
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  call       instance void [runtime]System.Object::.ctor()
+        IL_0006:  ldarg.0
+        IL_0007:  ldarg.1
+        IL_0008:  stfld      class MyTestModule/MyDu/MaybeString MyTestModule/MyDu/MaybeString@DebugTypeProxy::_obj
+        IL_000d:  ret
+      } 
+
+      .method public hidebysig instance string 
+              get_Item() cil managed
+      {
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        
+        .maxstack  8
+        IL_0000:  ldarg.0
+        IL_0001:  ldfld      class MyTestModule/MyDu/MaybeString MyTestModule/MyDu/MaybeString@DebugTypeProxy::_obj
+        IL_0006:  ldfld      string MyTestModule/MyDu/MaybeString::item
+        IL_000b:  ret
+      } 
+
+      .property instance string Item()
+      {
+        .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                    int32,
+                                                                                                    int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 00 00 00 00 ) 
+        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+        .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+        .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+        .get instance string MyTestModule/MyDu/MaybeString@DebugTypeProxy::get_Item()
+      } 
+    } 
+
+    .field static assembly initonly class MyTestModule/MyDu _unique_JustLabel
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .method private specialname rtspecialname static 
+            void  .cctor() cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  newobj     instance void MyTestModule/MyDu/_JustLabel::.ctor()
+      IL_0005:  stsfld     class MyTestModule/MyDu MyTestModule/MyDu::_unique_JustLabel
+      IL_000a:  ret
+    } 
+
+    .method assembly specialname rtspecialname 
+            instance void  .ctor() cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                              class [runtime]System.Type) = ( 01 00 E0 07 00 00 11 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                                     75 6C 65 2B 4D 79 44 75 00 00 )                   
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void [runtime]System.Object::.ctor()
+      IL_0006:  ret
+    } 
+
+    .method public static class MyTestModule/MyDu 
+            get_JustLabel() cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldsfld     class MyTestModule/MyDu MyTestModule/MyDu::_unique_JustLabel
+      IL_0005:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsJustLabel() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  isinst     MyTestModule/MyDu/_JustLabel
+      IL_0006:  ldnull
+      IL_0007:  cgt.un
+      IL_0009:  ret
+    } 
+
+    .method public static class MyTestModule/MyDu 
+            NewJustInt(int32 item) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  newobj     instance void MyTestModule/MyDu/JustInt::.ctor(int32)
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsJustInt() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  isinst     MyTestModule/MyDu/JustInt
+      IL_0006:  ldnull
+      IL_0007:  cgt.un
+      IL_0009:  ret
+    } 
+
+    .method public static class MyTestModule/MyDu 
+            NewMaybeString(string item) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 02 00 00 00 00 00 ) 
+      .param [1]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  newobj     instance void MyTestModule/MyDu/MaybeString::.ctor(string)
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsMaybeString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  isinst     MyTestModule/MyDu/MaybeString
+      IL_0006:  ldnull
+      IL_0007:  cgt.un
+      IL_0009:  ret
+    } 
+
+    .method public hidebysig instance int32 
+            get_Tag() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  isinst     MyTestModule/MyDu/MaybeString
+      IL_0006:  brfalse.s  IL_000b
+
+      IL_0008:  ldc.i4.2
+      IL_0009:  br.s       IL_0017
+
+      IL_000b:  ldarg.0
+      IL_000c:  isinst     MyTestModule/MyDu/JustInt
+      IL_0011:  brfalse.s  IL_0016
+
+      IL_0013:  ldc.i4.1
+      IL_0014:  br.s       IL_0017
+
+      IL_0016:  ldc.i4.0
+      IL_0017:  ret
+    } 
+
+    .method assembly hidebysig specialname 
+            instance object  __DebugDisplay() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+0.8A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+      IL_0015:  ret
+    } 
+
+    .method public strict virtual instance string 
+            ToString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class MyTestModule/MyDu>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+      IL_0015:  ret
+    } 
+
+    .property instance int32 Tag()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance int32 MyTestModule/MyDu::get_Tag()
+    } 
+    .property class MyTestModule/MyDu JustLabel()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get class MyTestModule/MyDu MyTestModule/MyDu::get_JustLabel()
+    } 
+    .property instance bool IsJustLabel()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool MyTestModule/MyDu::get_IsJustLabel()
+    } 
+    .property instance bool IsJustInt()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool MyTestModule/MyDu::get_IsJustInt()
+    } 
+    .property instance bool IsMaybeString()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool MyTestModule/MyDu::get_IsMaybeString()
+    } 
+  } 
+
+  .method public static class MyTestModule/MyDu 
+          giveMeLabel() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  call       class MyTestModule/MyDu MyTestModule/MyDu::get_JustLabel()
+    IL_0005:  ret
+  } 
+
+  .method public static class MyTestModule/MyDu 
+          createMaybeString(string innerValue) cil managed
+  {
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       class MyTestModule/MyDu MyTestModule/MyDu::NewMaybeString(string)
+    IL_0006:  ret
+  } 
+
+  .method public static string  processNullableDu(class MyTestModule/MyDu x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  5
+    .locals init (class MyTestModule/MyDu V_0,
+             class MyTestModule/MyDu V_1,
+             class MyTestModule/MyDu/JustInt V_2,
+             int32 V_3,
+             int32 V_4,
+             class MyTestModule/MyDu/MaybeString V_5,
+             string V_6)
+    IL_0000:  ldarg.0
+    IL_0001:  stloc.0
+    IL_0002:  ldloc.0
+    IL_0003:  brfalse.s  IL_0019
+
+    IL_0005:  ldloc.0
+    IL_0006:  stloc.1
+    IL_0007:  ldloc.1
+    IL_0008:  isinst     MyTestModule/MyDu/JustInt
+    IL_000d:  brtrue.s   IL_001d
+
+    IL_000f:  ldloc.1
+    IL_0010:  isinst     MyTestModule/MyDu/MaybeString
+    IL_0015:  brtrue.s   IL_0048
+
+    IL_0017:  br.s       IL_001b
+
+    IL_0019:  ldnull
+    IL_001a:  ret
+
+    IL_001b:  ldnull
+    IL_001c:  ret
+
+    IL_001d:  ldloc.0
+    IL_001e:  castclass  MyTestModule/MyDu/JustInt
+    IL_0023:  stloc.2
+    IL_0024:  ldloc.2
+    IL_0025:  ldfld      int32 MyTestModule/MyDu/JustInt::item
+    IL_002a:  stloc.3
+    IL_002b:  ldloc.3
+    IL_002c:  stloc.s    V_4
+    IL_002e:  ldloc.s    V_4
+    IL_0030:  box        [runtime]System.Int32
+    IL_0035:  unbox.any  [runtime]System.IFormattable
+    IL_003a:  ldnull
+    IL_003b:  call       class [netstandard]System.Globalization.CultureInfo [netstandard]System.Globalization.CultureInfo::get_InvariantCulture()
+    IL_0040:  tail.
+    IL_0042:  callvirt   instance string [netstandard]System.IFormattable::ToString(string,
+                                                                                    class [netstandard]System.IFormatProvider)
+    IL_0047:  ret
+
+    IL_0048:  ldloc.0
+    IL_0049:  castclass  MyTestModule/MyDu/MaybeString
+    IL_004e:  stloc.s    V_5
+    IL_0050:  ldloc.s    V_5
+    IL_0052:  ldfld      string MyTestModule/MyDu/MaybeString::item
+    IL_0057:  stloc.s    V_6
+    IL_0059:  ldloc.s    V_6
+    IL_005b:  ret
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs
new file mode 100644
index 00000000000..2571094f73f
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs
@@ -0,0 +1,13 @@
+module MyTestModule
+
+[]
+[]
+type MyStructDU = 
+    | A
+    | B of nonNullableString:string         // Tricky as the field WILL be null for tags other than B
+    | C of nullableString:(string | null)   // The field behind this is always nullable
+
+let getVal x = 
+    match x with
+    | C text -> text
+    | _ -> failwith "fail"
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.net472.bsl
new file mode 100644
index 00000000000..f2b77a10594
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.net472.bsl
@@ -0,0 +1,574 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .class sequential autochar serializable sealed nested public beforefieldinit Myassembly
+         extends [runtime]System.ValueType
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                   61 79 28 29 2C 6E 71 7D 00 00 )                   
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .class abstract auto ansi sealed nested public Tags
+           extends [runtime]System.Object
+    {
+      .field public static literal int32 A = int32(0x00000000)
+      .field public static literal int32 B = int32(0x00000001)
+      .field public static literal int32 C = int32(0x00000002)
+    } 
+
+    .field assembly string _nonNullableString
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly string _nullableString
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly int32 _tag
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .method public static valuetype MyTestModule/Myassembly 
+            get_A() cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldc.i4.0
+      IL_0001:  newobj     instance void MyTestModule/Myassembly::.ctor(int32)
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsA() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance int32 MyTestModule/Myassembly::get_Tag()
+      IL_0006:  ldc.i4.0
+      IL_0007:  ceq
+      IL_0009:  ret
+    } 
+
+    .method public static valuetype MyTestModule/Myassembly 
+            NewB(string _nonNullableString) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
+      
+      .maxstack  2
+      .locals init (valuetype MyTestModule/Myassembly V_0)
+      IL_0000:  ldloca.s   V_0
+      IL_0002:  initobj    MyTestModule/Myassembly
+      IL_0008:  ldloca.s   V_0
+      IL_000a:  ldc.i4.1
+      IL_000b:  stfld      int32 MyTestModule/Myassembly::_tag
+      IL_0010:  ldloca.s   V_0
+      IL_0012:  ldarg.0
+      IL_0013:  stfld      string MyTestModule/Myassembly::_nonNullableString
+      IL_0018:  ldloc.0
+      IL_0019:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsB() cil managed
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
+                                                                                              string[]) = ( 01 00 01 02 00 00 00 11 6E 6F 6E 4E 75 6C 6C 61   
+                                                                                                            62 6C 65 53 74 72 69 6E 67 12 5F 6E 6F 6E 4E 75   
+                                                                                                            6C 6C 61 62 6C 65 53 74 72 69 6E 67 00 00 )       
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance int32 MyTestModule/Myassembly::get_Tag()
+      IL_0006:  ldc.i4.1
+      IL_0007:  ceq
+      IL_0009:  ret
+    } 
+
+    .method public static valuetype MyTestModule/Myassembly 
+            NewC(string _nullableString) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 02 00 00 00 00 00 ) 
+      .param [1]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  2
+      .locals init (valuetype MyTestModule/Myassembly V_0)
+      IL_0000:  ldloca.s   V_0
+      IL_0002:  initobj    MyTestModule/Myassembly
+      IL_0008:  ldloca.s   V_0
+      IL_000a:  ldc.i4.2
+      IL_000b:  stfld      int32 MyTestModule/Myassembly::_tag
+      IL_0010:  ldloca.s   V_0
+      IL_0012:  ldarg.0
+      IL_0013:  stfld      string MyTestModule/Myassembly::_nullableString
+      IL_0018:  ldloc.0
+      IL_0019:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsC() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance int32 MyTestModule/Myassembly::get_Tag()
+      IL_0006:  ldc.i4.2
+      IL_0007:  ceq
+      IL_0009:  ret
+    } 
+
+    .method assembly specialname rtspecialname 
+            instance void  .ctor(int32 _tag) cil managed
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                              class [runtime]System.Type) = ( 01 00 60 06 00 00 17 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                               75 6C 65 2B 4D 79 53 74 72 75 63 74 44 55 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldarg.1
+      IL_0002:  stfld      int32 MyTestModule/Myassembly::_tag
+      IL_0007:  ret
+    } 
+
+    .method public hidebysig instance string 
+            get_nonNullableString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string MyTestModule/Myassembly::_nonNullableString
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance string 
+            get_nullableString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string MyTestModule/Myassembly::_nullableString
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance int32 
+            get_Tag() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      int32 MyTestModule/Myassembly::_tag
+      IL_0006:  ret
+    } 
+
+    .method assembly hidebysig specialname 
+            instance object  __DebugDisplay() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+0.8A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  ldobj      MyTestModule/Myassembly
+      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+      IL_001a:  ret
+    } 
+
+    .method public strict virtual instance string 
+            ToString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,valuetype MyTestModule/Myassembly>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  ldobj      MyTestModule/Myassembly
+      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+      IL_001a:  ret
+    } 
+
+    .property instance int32 Tag()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance int32 MyTestModule/Myassembly::get_Tag()
+    } 
+    .property valuetype MyTestModule/Myassembly
+            A()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get valuetype MyTestModule/Myassembly MyTestModule/Myassembly::get_A()
+    } 
+    .property instance bool IsA()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool MyTestModule/Myassembly::get_IsA()
+    } 
+    .property instance bool IsB()
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
+                                                                                              string[]) = ( 01 00 01 02 00 00 00 11 6E 6F 6E 4E 75 6C 6C 61   
+                                                                                                            62 6C 65 53 74 72 69 6E 67 12 5F 6E 6F 6E 4E 75   
+                                                                                                            6C 6C 61 62 6C 65 53 74 72 69 6E 67 00 00 )       
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool MyTestModule/Myassembly::get_IsB()
+    } 
+    .property instance bool IsC()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool MyTestModule/Myassembly::get_IsC()
+    } 
+    .property instance string nonNullableString()
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance string MyTestModule/Myassembly::get_nonNullableString()
+    } 
+    .property instance string nullableString()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 00 00 00 00 ) 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance string MyTestModule/Myassembly::get_nullableString()
+    } 
+  } 
+
+  .method public static string  getVal(valuetype MyTestModule/Myassembly x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  3
+    .locals init (valuetype MyTestModule/Myassembly V_0,
+             string V_1,
+             string V_2)
+    IL_0000:  ldarg.0
+    IL_0001:  stloc.0
+    IL_0002:  ldloca.s   V_0
+    IL_0004:  call       instance int32 MyTestModule/Myassembly::get_Tag()
+    IL_0009:  ldc.i4.2
+    IL_000a:  bne.un.s   IL_0016
+
+    IL_000c:  ldloca.s   V_0
+    IL_000e:  ldfld      string MyTestModule/Myassembly::_nullableString
+    IL_0013:  stloc.1
+    IL_0014:  ldloc.1
+    IL_0015:  ret
+
+    IL_0016:  ldstr      "fail"
+    IL_001b:  stloc.2
+    IL_001c:  ldloc.2
+    IL_001d:  call       class [runtime]System.Exception [FSharp.Core]Microsoft.FSharp.Core.Operators::Failure(string)
+    IL_0022:  throw
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi serializable sealed System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes
+       extends [runtime]System.Enum
+{
+  .custom instance void [runtime]System.FlagsAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public specialname rtspecialname int32 value__
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes All = int32(0xFFFFFFFF)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes None = int32(0x00000000)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicParameterlessConstructor = int32(0x00000001)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicConstructors = int32(0x00000003)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicConstructors = int32(0x00000004)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicMethods = int32(0x00000008)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicMethods = int32(0x00000010)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicFields = int32(0x00000020)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicFields = int32(0x00000040)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicNestedTypes = int32(0x00000080)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicNestedTypes = int32(0x00000100)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicProperties = int32(0x00000200)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicProperties = int32(0x00000400)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicEvents = int32(0x00000800)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicEvents = int32(0x00001000)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes Interfaces = int32(0x00002000)
+} 
+
+.class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute
+       extends [runtime]System.Attribute
+{
+  .field private valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field private class [runtime]System.Type Type@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType,
+                               class [runtime]System.Type Type) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::MemberType@
+    IL_000d:  ldarg.0
+    IL_000e:  ldarg.2
+    IL_000f:  stfld      class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::Type@
+    IL_0014:  ret
+  } 
+
+  .method public hidebysig specialname instance class [runtime]System.Type 
+          get_Type() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::Type@
+    IL_0006:  ret
+  } 
+
+  .method public hidebysig specialname instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes 
+          get_MemberType() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::MemberType@
+    IL_0006:  ret
+  } 
+
+  .property instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes
+          MemberType()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::get_MemberType()
+  } 
+  .property instance class [runtime]System.Type
+          Type()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::get_Type()
+  } 
+} 
+
+.class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute
+       extends [runtime]System.Attribute
+{
+  .field private bool ReturnValue@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field private string[] Members@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(bool ReturnValue,
+                               string[] Members) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      bool System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::ReturnValue@
+    IL_000d:  ldarg.0
+    IL_000e:  ldarg.2
+    IL_000f:  stfld      string[] System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::Members@
+    IL_0014:  ret
+  } 
+
+  .method public hidebysig specialname instance string[] 
+          get_Members() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      string[] System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::Members@
+    IL_0006:  ret
+  } 
+
+  .method public hidebysig specialname instance bool 
+          get_ReturnValue() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      bool System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::ReturnValue@
+    IL_0006:  ret
+  } 
+
+  .property instance bool ReturnValue()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance bool System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::get_ReturnValue()
+  } 
+  .property instance string[] Members()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance string[] System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::get_Members()
+  } 
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.netcore.bsl
new file mode 100644
index 00000000000..03597845da5
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.netcore.bsl
@@ -0,0 +1,415 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .class sequential autochar serializable sealed nested public beforefieldinit Myassembly
+         extends [runtime]System.ValueType
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                         61 79 28 29 2C 6E 71 7D 00 00 )                   
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .class abstract auto ansi sealed nested public Tags
+           extends [runtime]System.Object
+    {
+      .field public static literal int32 A = int32(0x00000000)
+      .field public static literal int32 B = int32(0x00000001)
+      .field public static literal int32 C = int32(0x00000002)
+    } 
+
+    .field assembly string _nonNullableString
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly string _nullableString
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly int32 _tag
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .method public static valuetype MyTestModule/Myassembly 
+            get_A() cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldc.i4.0
+      IL_0001:  newobj     instance void MyTestModule/Myassembly::.ctor(int32)
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsA() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance int32 MyTestModule/Myassembly::get_Tag()
+      IL_0006:  ldc.i4.0
+      IL_0007:  ceq
+      IL_0009:  ret
+    } 
+
+    .method public static valuetype MyTestModule/Myassembly 
+            NewB(string _nonNullableString) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
+      
+      .maxstack  2
+      .locals init (valuetype MyTestModule/Myassembly V_0)
+      IL_0000:  ldloca.s   V_0
+      IL_0002:  initobj    MyTestModule/Myassembly
+      IL_0008:  ldloca.s   V_0
+      IL_000a:  ldc.i4.1
+      IL_000b:  stfld      int32 MyTestModule/Myassembly::_tag
+      IL_0010:  ldloca.s   V_0
+      IL_0012:  ldarg.0
+      IL_0013:  stfld      string MyTestModule/Myassembly::_nonNullableString
+      IL_0018:  ldloc.0
+      IL_0019:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsB() cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
+                                                                                                              string[]) = ( 01 00 01 02 00 00 00 11 6E 6F 6E 4E 75 6C 6C 61   
+                                                                                                                            62 6C 65 53 74 72 69 6E 67 12 5F 6E 6F 6E 4E 75   
+                                                                                                                            6C 6C 61 62 6C 65 53 74 72 69 6E 67 00 00 )       
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance int32 MyTestModule/Myassembly::get_Tag()
+      IL_0006:  ldc.i4.1
+      IL_0007:  ceq
+      IL_0009:  ret
+    } 
+
+    .method public static valuetype MyTestModule/Myassembly 
+            NewC(string _nullableString) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 02 00 00 00 00 00 ) 
+      .param [1]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  2
+      .locals init (valuetype MyTestModule/Myassembly V_0)
+      IL_0000:  ldloca.s   V_0
+      IL_0002:  initobj    MyTestModule/Myassembly
+      IL_0008:  ldloca.s   V_0
+      IL_000a:  ldc.i4.2
+      IL_000b:  stfld      int32 MyTestModule/Myassembly::_tag
+      IL_0010:  ldloca.s   V_0
+      IL_0012:  ldarg.0
+      IL_0013:  stfld      string MyTestModule/Myassembly::_nullableString
+      IL_0018:  ldloc.0
+      IL_0019:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsC() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance int32 MyTestModule/Myassembly::get_Tag()
+      IL_0006:  ldc.i4.2
+      IL_0007:  ceq
+      IL_0009:  ret
+    } 
+
+    .method assembly specialname rtspecialname 
+            instance void  .ctor(int32 _tag) cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                              class [runtime]System.Type) = ( 01 00 60 06 00 00 17 4D 79 54 65 73 74 4D 6F 64   
+                                                                                                                                                     75 6C 65 2B 4D 79 53 74 72 75 63 74 44 55 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldarg.1
+      IL_0002:  stfld      int32 MyTestModule/Myassembly::_tag
+      IL_0007:  ret
+    } 
+
+    .method public hidebysig instance string 
+            get_nonNullableString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string MyTestModule/Myassembly::_nonNullableString
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance string 
+            get_nullableString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string MyTestModule/Myassembly::_nullableString
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance int32 
+            get_Tag() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      int32 MyTestModule/Myassembly::_tag
+      IL_0006:  ret
+    } 
+
+    .method assembly hidebysig specialname 
+            instance object  __DebugDisplay() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+0.8A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  ldobj      MyTestModule/Myassembly
+      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+      IL_001a:  ret
+    } 
+
+    .method public strict virtual instance string 
+            ToString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,valuetype MyTestModule/Myassembly>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  ldobj      MyTestModule/Myassembly
+      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+      IL_001a:  ret
+    } 
+
+    .property instance int32 Tag()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance int32 MyTestModule/Myassembly::get_Tag()
+    } 
+    .property valuetype MyTestModule/Myassembly
+            A()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get valuetype MyTestModule/Myassembly MyTestModule/Myassembly::get_A()
+    } 
+    .property instance bool IsA()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool MyTestModule/Myassembly::get_IsA()
+    } 
+    .property instance bool IsB()
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
+                                                                                                              string[]) = ( 01 00 01 02 00 00 00 11 6E 6F 6E 4E 75 6C 6C 61   
+                                                                                                                            62 6C 65 53 74 72 69 6E 67 12 5F 6E 6F 6E 4E 75   
+                                                                                                                            6C 6C 61 62 6C 65 53 74 72 69 6E 67 00 00 )       
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool MyTestModule/Myassembly::get_IsB()
+    } 
+    .property instance bool IsC()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool MyTestModule/Myassembly::get_IsC()
+    } 
+    .property instance string nonNullableString()
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance string MyTestModule/Myassembly::get_nonNullableString()
+    } 
+    .property instance string nullableString()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 00 00 00 00 ) 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance string MyTestModule/Myassembly::get_nullableString()
+    } 
+  } 
+
+  .method public static string  getVal(valuetype MyTestModule/Myassembly x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  3
+    .locals init (valuetype MyTestModule/Myassembly V_0,
+             string V_1,
+             string V_2)
+    IL_0000:  ldarg.0
+    IL_0001:  stloc.0
+    IL_0002:  ldloca.s   V_0
+    IL_0004:  call       instance int32 MyTestModule/Myassembly::get_Tag()
+    IL_0009:  ldc.i4.2
+    IL_000a:  bne.un.s   IL_0016
+
+    IL_000c:  ldloca.s   V_0
+    IL_000e:  ldfld      string MyTestModule/Myassembly::_nullableString
+    IL_0013:  stloc.1
+    IL_0014:  ldloc.1
+    IL_0015:  ret
+
+    IL_0016:  ldstr      "fail"
+    IL_001b:  stloc.2
+    IL_001c:  ldloc.2
+    IL_001d:  call       class [runtime]System.Exception [FSharp.Core]Microsoft.FSharp.Core.Operators::Failure(string)
+    IL_0022:  throw
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index c44ce76ff6b..f5a1b336130 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -157,6 +157,7 @@
     
     
     
+    
     
     
     
diff --git a/tests/adhoc/nullness/out.fsi b/tests/adhoc/nullness/out.fsi
new file mode 100644
index 00000000000..10b41edf5ca
--- /dev/null
+++ b/tests/adhoc/nullness/out.fsi
@@ -0,0 +1,346 @@
+
+module FSharp.BuildProperties
+
+val internal fsProductVersion: string
+
+val internal fsLanguageVersion: string
+
+
+
+namespace FSharp
+
+
+module ExistingPositive
+
+module Extractions0a =
+    
+    val x: 'a | null
+    
+    val result: bool
+
+module Extractions0b =
+    
+    val x: 'a | null
+    
+    val f: x: 'T * y: 'T -> unit
+    
+    val result: unit
+
+module Extractions0d =
+    
+    val x: 'a | null
+    
+    val f: x: 'T * y: 'T -> unit when 'T: null
+    
+    val result: unit
+
+module Basics =
+    
+    val x1: System.String
+    
+    val x4: System.String
+
+module Basics2 =
+    
+    val f1: unit -> 'a | null
+    
+    val f8: unit -> System.String
+
+type C =
+    
+    new: s: System.String -> C
+    
+    member Value: System.String
+
+module InteropBasics =
+    
+    val s0: string
+    
+    val s1: System.String
+    
+    val test1: unit -> string
+    
+    val test2: s1: System.String * s2: System.String -> string
+    
+    val test3: unit -> System.String
+    
+    val test4: unit -> System.AppDomain
+    
+    val test5: System.AppDomain
+
+val f0: line: string -> unit
+
+module NullConstraintTests =
+    
+    type C<'T when 'T: null> =
+        
+        new: unit -> C<'T>
+    
+    val f3: y: C -> C
+
+module DefaultValueTests =
+    
+    module StructExamples =
+        
+        []
+        type C2 =
+            
+            []
+            val mutable Whoops: System.String
+    
+    module ClassExamples =
+        
+        type C2 =
+            
+            []
+            val mutable Whoops: System.String
+
+
+module EnabledPositive
+
+module Basics =
+    
+    val x2: System.String | null
+    
+    val x3: System.String | null
+
+module NotNullConstraint =
+    
+    val f3: x: 'T -> int when 'T: not null
+    
+    val v1: int
+    
+    val v2: int
+    
+    val v3: int
+    
+    val v4: int
+    
+    val v5: int
+    
+    val w1: int
+    
+    val w2: int
+    
+    val w3: int
+    
+    val w4: int
+    
+    val w5: int
+
+module MemberBasics =
+    
+    type C =
+        
+        new: unit -> C
+        
+        member M: unit -> int
+        
+        member P: int
+    
+    val c: C | null
+    
+    val v1: int
+    
+    val v2: int
+    
+    val f1: (unit -> int)
+
+module Basics2 =
+    
+    val f1: unit -> 'a | null
+    
+    val f2: unit -> System.String | null
+    
+    val f3: unit -> 'T | null when 'T: not null
+    
+    val f4: unit -> 'T | null when 'T: not null and 'T: not struct
+    
+    val f5: unit -> 'T when 'T: not struct and 'T: null
+    
+    val f8: unit -> System.String
+
+type C =
+    
+    new: s: System.String -> C
+    
+    member Value: System.String
+
+val f: x: 'T | null * y: 'T | null -> unit when 'T: not null
+
+module Extractions0c =
+    
+    val x: 'a | null
+    
+    val f: x: 'T | null * y: 'T | null -> unit when 'T: not null
+    
+    val s: System.String
+    
+    val result: unit
+
+module Extractions0e =
+    
+    val x: 'a | null
+    
+    val f: x: 'T | null * y: 'T | null -> unit when 'T: not null
+    
+    val result: unit
+
+module Extractions1 =
+    
+    val mutable x: string
+
+module InteropBasics =
+    
+    val s0: string
+    
+    val s1: System.String
+    
+    val test1: unit -> string
+    
+    val test2: s1: System.String * s2: System.String -> string
+    
+    val test3: unit -> System.String
+    
+    val test4: unit -> System.AppDomain
+    
+    val test5: System.AppDomain
+
+[]
+type KonsoleWithNulls =
+    
+    static member WriteLine: s: System.String -> unit
+    
+    static member
+      WriteLine: fmt: System.String * [] args: obj array ->
+                   unit
+    
+    static member WriteLine: fmt: System.String * arg1: System.String -> unit
+    
+    static member WriteLineC: s: C -> unit
+    
+    static member WriteLineC: fmt: C * arg1: C -> unit
+
+module KonsoleWithNullsModule =
+    
+    val WriteLine: s: System.String | null -> unit
+    
+    val WriteLine2:
+      fmt: System.String | null * arg1: System.String | null -> unit
+    
+    val WriteLineC: s: C | null -> unit
+    
+    val WriteLineC2: fmt: C | null * arg1: C | null -> unit
+
+module KonsoleWithNullsModule2 =
+    
+    val WriteLine: x: System.String | null -> unit
+    
+    val WriteLine2:
+      fmt: System.String | null * arg1: System.String | null -> unit
+    
+    val WriteLineC: s: C | null -> unit
+    
+    val WriteLineC2: fmt: C | null * arg1: C | null -> unit
+
+[]
+type KonsoleNoNulls =
+    
+    static member WriteLine: s: System.String -> unit
+    
+    static member
+      WriteLine: fmt: System.String * [] args: obj array ->
+                   unit
+    
+    static member WriteLine: fmt: System.String * arg1: System.String -> unit
+    
+    static member WriteLineC: s: C -> unit
+    
+    static member WriteLineC: fmt: C * arg1: C -> unit
+
+module KonsoleNoNullsModule =
+    
+    val WriteLine: s: System.String -> unit
+    
+    val WriteLine2: fmt: System.String * arg1: System.String -> unit
+    
+    val WriteLineC: s: C -> unit
+    
+    val WriteLineC2: fmt: C * arg1: C -> unit
+
+module KonsoleNoNullsModule2 =
+    
+    val WriteLine: x: System.String -> unit
+    
+    val WriteLine2: fmt: System.String * arg1: System.String -> unit
+    
+    val WriteLineC: s: C -> unit
+    
+    val WriteLineC2: fmt: C * arg1: C -> unit
+
+val f0: line: string -> unit
+
+module NullConstraintTests =
+    
+    type C<'T when 'T: null> =
+        
+        new: unit -> C<'T>
+    
+    val f3: y: C -> C
+    
+    val f4: y: C -> C
+    
+    val f5: y: C | null> -> C | null>
+    
+    val f6: y: C | null> -> C | null>
+
+module DefaultValueTests =
+    
+    module StructExamples =
+        
+        []
+        type C2 =
+            
+            []
+            val mutable Whoops: System.String
+        
+        []
+        type C3 =
+            
+            []
+            val mutable Whoops: System.String | null
+        
+        []
+        type C4b =
+            
+            []
+            val mutable Whoops: List | null
+        
+        []
+        type C7 =
+            
+            []
+            val mutable Whoops: (int -> int | null)
+    
+    module ClassExamples =
+        
+        type C2 =
+            
+            []
+            val mutable Whoops: System.String
+        
+        type C3 =
+            
+            []
+            val mutable Whoops: System.String | null
+        
+        type C4b =
+            
+            []
+            val mutable Whoops: List | null
+        
+        type C7 =
+            
+            []
+            val mutable Whoops: (int -> int | null)
+

From c5b378157a69f11e0259612422c1e54f60eb530d Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Tue, 28 Nov 2023 13:12:55 +0100
Subject: [PATCH 32/59] fix merge mistake

---
 src/Compiler/Driver/CompilerImports.fs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Compiler/Driver/CompilerImports.fs b/src/Compiler/Driver/CompilerImports.fs
index 306b0455fab..8b106683b29 100644
--- a/src/Compiler/Driver/CompilerImports.fs
+++ b/src/Compiler/Driver/CompilerImports.fs
@@ -2148,7 +2148,7 @@ and [] TcImports
                         | None -> None
                         | Some (readerA, readerB) ->
                             let data =
-                                GetOptimizationData(fileName, ilScopeRef, ilModule.TryGetILModuleDef(), readerA, readerB))
+                                GetOptimizationData(fileName, ilScopeRef, ilModule.TryGetILModuleDef(), readerA, readerB)
 
                             let fixupThunk () =
                                 data.OptionalFixup(fun nm -> availableToOptionalCcu (tcImports.FindCcu(ctok, m, nm, lookupOnly = false)))

From 70adb59b22de45ae7bdecbc360ea10e4c0e5d00d Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Tue, 28 Nov 2023 14:48:47 +0100
Subject: [PATCH 33/59] fix build

---
 src/Compiler/CodeGen/IlxGenSupport.fs  |  4 +---
 src/Compiler/SyntaxTree/SyntaxTree.fs  |  1 +
 src/Compiler/xlf/FSStrings.cs.xlf      | 25 +++++++++++++++++++++++++
 src/Compiler/xlf/FSStrings.de.xlf      | 25 +++++++++++++++++++++++++
 src/Compiler/xlf/FSStrings.es.xlf      | 25 +++++++++++++++++++++++++
 src/Compiler/xlf/FSStrings.fr.xlf      | 25 +++++++++++++++++++++++++
 src/Compiler/xlf/FSStrings.it.xlf      | 25 +++++++++++++++++++++++++
 src/Compiler/xlf/FSStrings.ja.xlf      | 25 +++++++++++++++++++++++++
 src/Compiler/xlf/FSStrings.ko.xlf      | 25 +++++++++++++++++++++++++
 src/Compiler/xlf/FSStrings.pl.xlf      | 25 +++++++++++++++++++++++++
 src/Compiler/xlf/FSStrings.pt-BR.xlf   | 25 +++++++++++++++++++++++++
 src/Compiler/xlf/FSStrings.ru.xlf      | 25 +++++++++++++++++++++++++
 src/Compiler/xlf/FSStrings.tr.xlf      | 25 +++++++++++++++++++++++++
 src/Compiler/xlf/FSStrings.zh-Hans.xlf | 25 +++++++++++++++++++++++++
 src/Compiler/xlf/FSStrings.zh-Hant.xlf | 25 +++++++++++++++++++++++++
 15 files changed, 327 insertions(+), 3 deletions(-)

diff --git a/src/Compiler/CodeGen/IlxGenSupport.fs b/src/Compiler/CodeGen/IlxGenSupport.fs
index 3f2778b0678..40b265d1d49 100644
--- a/src/Compiler/CodeGen/IlxGenSupport.fs
+++ b/src/Compiler/CodeGen/IlxGenSupport.fs
@@ -135,8 +135,6 @@ let mkLocalPrivateAttributeWithPropertyConstructors
             )
         )
 
-    let ilCustomAttrs = mkILCustomAttrsFromArray [| g.CompilerGeneratedAttribute |]
-
     mkILGenericClass (
         name,
         ILTypeDefAccess.Private,
@@ -213,7 +211,7 @@ let mkLocalPrivateAttributeWithByteAndByteArrayConstructors (g: TcGlobals, name:
         emptyILTypeDefs,
         emptyILProperties,
         emptyILEvents,
-        ilCustomAttrs,
+        mkILCustomAttrsFromArray [| g.CompilerGeneratedAttribute |],
         ILTypeInit.BeforeField
     )
 
diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs
index 8070d6ebc29..6c1c182268f 100644
--- a/src/Compiler/SyntaxTree/SyntaxTree.fs
+++ b/src/Compiler/SyntaxTree/SyntaxTree.fs
@@ -348,6 +348,7 @@ type SynTypeConstraint =
         | WhereTyparIsReferenceType(range = range)
         | WhereTyparIsUnmanaged(range = range)
         | WhereTyparSupportsNull(range = range)
+        | WhereTyparNotSupportsNull(range = range)
         | WhereTyparIsComparable(range = range)
         | WhereTyparIsEquatable(range = range)
         | WhereTyparDefaultsToType(range = range)
diff --git a/src/Compiler/xlf/FSStrings.cs.xlf b/src/Compiler/xlf/FSStrings.cs.xlf
index 318ea1464ff..b2a4e04e6c4 100644
--- a/src/Compiler/xlf/FSStrings.cs.xlf
+++ b/src/Compiler/xlf/FSStrings.cs.xlf
@@ -7,6 +7,26 @@
         Názvy argumentů v signatuře {0} a implementaci {1} si neodpovídají. Použije se název argumentu ze souboru signatury. To může způsobit problémy při ladění nebo profilování.
         
       
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Neshoda typů Očekává se řazená kolekce členů o délce {0} typu\n    {1}    \nale odevzdala se řazená kolekce členů o délce {2} typu\n    {3}{4}\n
@@ -32,6 +52,11 @@
          Static member is expected.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         symbol ..^
diff --git a/src/Compiler/xlf/FSStrings.de.xlf b/src/Compiler/xlf/FSStrings.de.xlf
index 430b308631e..3178a6def03 100644
--- a/src/Compiler/xlf/FSStrings.de.xlf
+++ b/src/Compiler/xlf/FSStrings.de.xlf
@@ -7,6 +7,26 @@
         Die Argumentnamen in Signatur "{0}" und Implementierung "{1}" stimmen nicht überein. Der Argumentname aus der Signaturdatei wird verwendet. Dadurch können Probleme beim Debuggen oder bei der Profilerstellung auftreten.
         
       
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Typenkonflikt. Es wurde ein Tupel der Länge {0} des Typs\n    {1}    \nerwartet, aber ein Tupel der Länge {2} des Typs\n    {3}{4}\n angegeben.
@@ -32,6 +52,11 @@
          Static member is expected.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         Symbol "..^"
diff --git a/src/Compiler/xlf/FSStrings.es.xlf b/src/Compiler/xlf/FSStrings.es.xlf
index 9a94fe0bfca..7b2e668ea61 100644
--- a/src/Compiler/xlf/FSStrings.es.xlf
+++ b/src/Compiler/xlf/FSStrings.es.xlf
@@ -7,6 +7,26 @@
         Los nombres de argumento en la firma "{0}" y la implementación "{1}" no coinciden. Se utilizará el nombre del argumento desde el archivo de firma. Esto puede causar problemas durante la depuración o la generación de perfiles.
         
       
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Error de coincidencia de tipos. Se espera una tupla de longitud {0} de tipo\n    {1}    \nperero se ha proporcionado una tupla de longitud {2} de tipo\n    {3}{4}\n
@@ -32,6 +52,11 @@
          Static member is expected.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         símbolo "..^"
diff --git a/src/Compiler/xlf/FSStrings.fr.xlf b/src/Compiler/xlf/FSStrings.fr.xlf
index 0d5bfd687ae..35581a00f2d 100644
--- a/src/Compiler/xlf/FSStrings.fr.xlf
+++ b/src/Compiler/xlf/FSStrings.fr.xlf
@@ -7,6 +7,26 @@
         Les noms d'arguments dans la signature '{0}' et l'implémentation '{1}' ne correspondent pas. Le nom d'argument du fichier de signature va être utilisé. Cela peut entraîner des problèmes durant le débogage ou le profilage.
         
       
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Incompatibilité de type. Tuple de longueur attendu {0} de type\n {1} \nmais tuple de longueur {2} de type\n    {3}{4}\n
@@ -32,6 +52,11 @@
          Static member is expected.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         symbole '..^'
diff --git a/src/Compiler/xlf/FSStrings.it.xlf b/src/Compiler/xlf/FSStrings.it.xlf
index 465456a085d..5fc7bbeeec9 100644
--- a/src/Compiler/xlf/FSStrings.it.xlf
+++ b/src/Compiler/xlf/FSStrings.it.xlf
@@ -7,6 +7,26 @@
         I nomi degli argomenti nella firma '{0}' e nell'implementazione '{1}' non corrispondono. Verrà usato il nome dell'argomento del file di firma. Questa situazione potrebbe causare problemi durante il debug o la profilatura.
         
       
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Tipo non corrispondente. È prevista una tupla di lunghezza {0} di tipo\n   {1}    \n, ma è stata specificata una tupla di lunghezza {2} di tipo\n    {3}{4}\n
@@ -32,6 +52,11 @@
          Static member is expected.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         simbolo '..^'
diff --git a/src/Compiler/xlf/FSStrings.ja.xlf b/src/Compiler/xlf/FSStrings.ja.xlf
index c895e7a6a1e..103a4edeca0 100644
--- a/src/Compiler/xlf/FSStrings.ja.xlf
+++ b/src/Compiler/xlf/FSStrings.ja.xlf
@@ -7,6 +7,26 @@
         シグネチャ '{0}' と実装 '{1}' の引数の名前が一致しません。シグネチャ ファイルの引数の名前が使用されます。デバッグまたはプロファイルするときに問題が生じる原因となる可能性があります。
         
       
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         型が一致しません。型の長さ {0} のタプルが必要です\n    {1}    \nただし、型の長さ {2} のタプルが指定された場合\n    {3}{4}\n
@@ -32,6 +52,11 @@
          Static member is expected.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         シンボル '..^'
diff --git a/src/Compiler/xlf/FSStrings.ko.xlf b/src/Compiler/xlf/FSStrings.ko.xlf
index 82dbc42e072..812dcd965b2 100644
--- a/src/Compiler/xlf/FSStrings.ko.xlf
+++ b/src/Compiler/xlf/FSStrings.ko.xlf
@@ -7,6 +7,26 @@
         시그니처 '{0}'과(와) 구현 '{1}'의 인수 이름이 일치하지 않습니다. 시그니처 파일의 인수 이름이 사용됩니다. 이로 인해 디버깅 또는 프로파일링 시 문제가 발생할 수 있습니다.
         
       
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         유형 불일치. 형식이 \n    {1}이고 길이가 {0}인 튜플이 필요합니다.    \n그러나 형식이 \n    {3}이고 길이가 {2}인 튜플이 제공되었습니다.{4}\n
@@ -32,6 +52,11 @@
          Static member is expected.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         기호 '..^'
diff --git a/src/Compiler/xlf/FSStrings.pl.xlf b/src/Compiler/xlf/FSStrings.pl.xlf
index e2bc31e3fb9..d10f929a4f1 100644
--- a/src/Compiler/xlf/FSStrings.pl.xlf
+++ b/src/Compiler/xlf/FSStrings.pl.xlf
@@ -7,6 +7,26 @@
         Nazwy argumentów w podpisie „{0}” i implementacji „{1}” nie są zgodne. Używana będzie nazwa argumentu z pliku podpisu. Może to spowodować problemy podczas debugowania lub profilowania.
         
       
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Niezgodność. Oczekiwano krotki o długości {0} typu\n    {1}    \nale otrzymano krotkę o długości {2} typu\n    {3}{4}\n
@@ -32,6 +52,11 @@
          Static member is expected.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         symbol „..^”
diff --git a/src/Compiler/xlf/FSStrings.pt-BR.xlf b/src/Compiler/xlf/FSStrings.pt-BR.xlf
index b4d1f7ba70d..3255d8c404d 100644
--- a/src/Compiler/xlf/FSStrings.pt-BR.xlf
+++ b/src/Compiler/xlf/FSStrings.pt-BR.xlf
@@ -7,6 +7,26 @@
         Os nomes de argumento na assinatura '{0}' e na implementação '{1}' não coincidem. O nome do argumento do arquivo da assinatura será usado. Isso pode causar problemas durante a depuração ou a criação de perfil.
         
       
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Tipo incompatível. Esperando uma tupla de comprimento {0} do tipo\n    {1}    \nmas recebeu uma tupla de comprimento {2} do tipo\n    {3}{4}\n
@@ -32,6 +52,11 @@
          Static member is expected.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         símbolo '..^'
diff --git a/src/Compiler/xlf/FSStrings.ru.xlf b/src/Compiler/xlf/FSStrings.ru.xlf
index 5149ef4d9f0..5de47b70a92 100644
--- a/src/Compiler/xlf/FSStrings.ru.xlf
+++ b/src/Compiler/xlf/FSStrings.ru.xlf
@@ -7,6 +7,26 @@
         Имена аргументов в сигнатуре "{0}" и реализации "{1}" не совпадают. Будет использоваться имя аргумента из файла сигнатуры. Это может вызвать проблемы при отладке или профилировании.
         
       
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Несоответствие типов. Ожидается кортеж длиной {0} типа\n    {1},    \nно предоставлен кортеж длиной {2} типа\n    {3}{4}\n
@@ -32,6 +52,11 @@
          Static member is expected.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         символ "..^"
diff --git a/src/Compiler/xlf/FSStrings.tr.xlf b/src/Compiler/xlf/FSStrings.tr.xlf
index dde4f9ee022..1fac64a8dc9 100644
--- a/src/Compiler/xlf/FSStrings.tr.xlf
+++ b/src/Compiler/xlf/FSStrings.tr.xlf
@@ -7,6 +7,26 @@
         {0}' imzası ve '{1}' uygulaması içindeki bağımsız değişken adları eşleşmiyor. İmza dosyasındaki bağımsız değişken adı kullanılacak. Bu, hata ayıklama veya profil oluşturma sırasında sorunlara neden olabilir.
         
       
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         Tür uyuşmazlığı. {0} uzunluğunda türü\n {1} \nolan bir demet bekleniyordu ancak {2} uzunluğunda türü\n    {3}{4}\nolan bir demet verildi
@@ -32,6 +52,11 @@
          Static member is expected.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         '..^' sembolü
diff --git a/src/Compiler/xlf/FSStrings.zh-Hans.xlf b/src/Compiler/xlf/FSStrings.zh-Hans.xlf
index 89e54bb26c5..8f4363d334a 100644
--- a/src/Compiler/xlf/FSStrings.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSStrings.zh-Hans.xlf
@@ -7,6 +7,26 @@
         签名“{0}”和实现“{1}”中的参数名称不匹配。将使用签名文件中的参数名称。在进行调试或分析时这可能会导致问题。
         
       
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         类型不匹配。应为长度为 {0} 的类型的元组\n    {1}    \n但提供了长度为 {2} 的类型的元组\n    {3}{4}\n
@@ -32,6 +52,11 @@
          Static member is expected.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         符号 "..^"
diff --git a/src/Compiler/xlf/FSStrings.zh-Hant.xlf b/src/Compiler/xlf/FSStrings.zh-Hant.xlf
index 71c045b02fa..e5aa888ced3 100644
--- a/src/Compiler/xlf/FSStrings.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSStrings.zh-Hant.xlf
@@ -7,6 +7,26 @@
         特徵標記 '{0}' 和實作 '{1}' 中的引數名稱不相符。將會使用特徵標記檔案中的引數名稱。這可能會在偵錯或分析時造成問題。
         
       
+      
+        Nullness warning: {0}.
+        Nullness warning: {0}.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have equivalent nullability.
+        
+      
+      
+        Nullness warning: The type '{0}' does not support 'null'.
+        Nullness warning: The type '{0}' does not support 'null'.
+        
+      
+      
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        Nullness warning: The types '{0}' and '{1}' do not have compatible nullability.
+        
+      
       
         Type mismatch. Expecting a tuple of length {0} of type\n    {1}    \nbut given a tuple of length {2} of type\n    {3}    {4}\n
         類型不符。必須是類型為\n    {1}    \n 的元組長度 {0},但提供的是類型為\n    {3}{4}\n 的元組長度 {2}
@@ -32,6 +52,11 @@
          Static member is expected.
         
       
+      
+        symbol '|' (directly before 'null')
+        symbol '|' (directly before 'null')
+        
+      
       
         symbol '..^'
         符號 '..^'

From 51ccb509bf9acdc133f3059cf511d7cebda87921 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Tue, 28 Nov 2023 14:55:26 +0100
Subject: [PATCH 34/59] fantomas

---
 src/Compiler/Checking/SignatureHash.fs        |  2 +-
 src/Compiler/CodeGen/EraseUnions.fs           | 11 +--
 src/Compiler/CodeGen/IlxGen.fs                |  3 +-
 src/Compiler/CodeGen/IlxGenSupport.fs         |  8 +-
 src/Compiler/Driver/CompilerDiagnostics.fs    | 34 ++++----
 .../GraphChecking/FileContentMapping.fs       | 10 +--
 src/Compiler/Interactive/fsi.fs               |  4 +-
 src/Compiler/Service/ServiceParseTreeWalk.fs  | 30 +++----
 src/Compiler/Service/ServiceParsedInputOps.fs | 86 +++++++++----------
 src/Compiler/SyntaxTree/SyntaxTree.fs         | 42 ++++-----
 10 files changed, 116 insertions(+), 114 deletions(-)

diff --git a/src/Compiler/Checking/SignatureHash.fs b/src/Compiler/Checking/SignatureHash.fs
index bf4b64b1b2a..2e22ca00ce4 100644
--- a/src/Compiler/Checking/SignatureHash.fs
+++ b/src/Compiler/Checking/SignatureHash.fs
@@ -164,7 +164,7 @@ module rec HashTypes =
         | TyparConstraint.IsReferenceType _ -> tpHash @@ 11
         | TyparConstraint.SimpleChoice(tys, _) -> tpHash @@ 12 @@ (tys |> hashListOrderIndependent (hashTType g))
         | TyparConstraint.RequiresDefaultConstructor _ -> tpHash @@ 13
-        | TyparConstraint.NotSupportsNull (_) -> tpHash @@ 14
+        | TyparConstraint.NotSupportsNull(_) -> tpHash @@ 14
 
     /// Hash type parameter constraints
     let private hashConstraints (g: TcGlobals) cxs =
diff --git a/src/Compiler/CodeGen/EraseUnions.fs b/src/Compiler/CodeGen/EraseUnions.fs
index 0ffbdd389a9..fc4f77d4730 100644
--- a/src/Compiler/CodeGen/EraseUnions.fs
+++ b/src/Compiler/CodeGen/EraseUnions.fs
@@ -1362,7 +1362,8 @@ let mkClassUnionDef
                                         match nullableIdx with
                                         | None ->
                                             existingAttrs
-                                            |> Array.append [| GetNullableAttribute g [ FSharp.Compiler.TypedTree.NullnessInfo.WithNull ] |]
+                                            |> Array.append
+                                                [| GetNullableAttribute g [ FSharp.Compiler.TypedTree.NullnessInfo.WithNull ] |]
                                         | Some idx ->
                                             let replacementAttr =
                                                 match existingAttrs[idx] with
@@ -1372,11 +1373,11 @@ let mkClassUnionDef
                                                  If the field was already declared as nullable (value = 2uy) or ambivalent(value = 0uy), we can keep it that way
                                                  If it was marked as non-nullable within that UnionCase, we have to convert it to WithNull (2uy) due to other cases being possible
                                                 *)
-                                                | Encoded (method, _data, [ ILAttribElem.Byte 1uy ]) ->
+                                                | Encoded(method, _data, [ ILAttribElem.Byte 1uy ]) ->
                                                     mkILCustomAttribMethRef (method, [ ILAttribElem.Byte 2uy ], [])
-                                                | Encoded (method,
-                                                           _data,
-                                                           [ ILAttribElem.Array (elemType, (ILAttribElem.Byte 1uy) :: otherElems) ]) ->
+                                                | Encoded(method,
+                                                          _data,
+                                                          [ ILAttribElem.Array(elemType, (ILAttribElem.Byte 1uy) :: otherElems) ]) ->
                                                     mkILCustomAttribMethRef (
                                                         method,
                                                         [ ILAttribElem.Array(elemType, (ILAttribElem.Byte 2uy) :: otherElems) ],
diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs
index a2a70665144..4e09ca60af0 100644
--- a/src/Compiler/CodeGen/IlxGen.fs
+++ b/src/Compiler/CodeGen/IlxGen.fs
@@ -10856,7 +10856,8 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) =
                                 customAttrs =
                                     mkILCustomAttrs (
                                         GenAttrs cenv eenv fattribs
-                                        @ extraAttribs @ GenAdditionalAttributesForTy g fspec.FormalType
+                                        @ extraAttribs
+                                        @ GenAdditionalAttributesForTy g fspec.FormalType
                                     )
                             )
                                 .WithAccess(access)
diff --git a/src/Compiler/CodeGen/IlxGenSupport.fs b/src/Compiler/CodeGen/IlxGenSupport.fs
index 40b265d1d49..87787697a00 100644
--- a/src/Compiler/CodeGen/IlxGenSupport.fs
+++ b/src/Compiler/CodeGen/IlxGenSupport.fs
@@ -392,7 +392,7 @@ Type parameter reference: the nullability (0, 1, or 2, with 0 for unconstrained
 *)
 let rec GetNullnessFromTType (g: TcGlobals) ty =
     match ty |> stripTyEqns g with
-    | TType_app (tcref, tinst, nullness) ->
+    | TType_app(tcref, tinst, nullness) ->
         let isValueType = tcref.IsStructOrEnumTycon
         let isNonGeneric = tinst.IsEmpty
 
@@ -415,7 +415,7 @@ let rec GetNullnessFromTType (g: TcGlobals) ty =
                     yield! GetNullnessFromTType g tt
             ]
 
-    | TType_fun (domainTy, retTy, nullness) ->
+    | TType_fun(domainTy, retTy, nullness) ->
         // FsharpFunc
         [
             yield nullness.Evaluate()
@@ -423,7 +423,7 @@ let rec GetNullnessFromTType (g: TcGlobals) ty =
             yield! GetNullnessFromTType g retTy
         ]
 
-    | TType_tuple (tupInfo, elementTypes) ->
+    | TType_tuple(tupInfo, elementTypes) ->
         // Tuple: the representation of the underlying constructed type
         [
             if evalTupInfoIsStruct tupInfo then
@@ -434,7 +434,7 @@ let rec GetNullnessFromTType (g: TcGlobals) ty =
                 yield! GetNullnessFromTType g t
         ]
 
-    | TType_anon (anonInfo, tys) ->
+    | TType_anon(anonInfo, tys) ->
         // It is unlikely for an anon type to be used from C# due to the mangled name, but can still carry the nullability info about it's generic type arguments == the types of the fields
         [
             if evalAnonInfoIsStruct anonInfo then
diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs
index 62e36015fe1..9db4d1acf2f 100644
--- a/src/Compiler/Driver/CompilerDiagnostics.fs
+++ b/src/Compiler/Driver/CompilerDiagnostics.fs
@@ -172,18 +172,18 @@ type Exception with
         | UnresolvedConversionOperator(_, _, _, m)
         | VirtualAugmentationOnNullValuedType m
         | NonVirtualAugmentationOnNullValuedType m
-        | NonRigidTypar (_, _, _, _, _, m)
-        | ConstraintSolverTupleDiffLengths (_, _, _, _, m, _)
-        | ConstraintSolverInfiniteTypes (_, _, _, _, m, _)
-        | ConstraintSolverMissingConstraint (_, _, _, m, _)
-        | ConstraintSolverNullnessWarningEquivWithTypes (_, _, _, _, _, m, _)
-        | ConstraintSolverNullnessWarningWithTypes (_, _, _, _, _, m, _)
-        | ConstraintSolverNullnessWarningWithType (_, _, _, m, _)
-        | ConstraintSolverNullnessWarning (_, m, _)
-        | ConstraintSolverTypesNotInEqualityRelation (_, _, _, m, _, _)
-        | ConstraintSolverError (_, m, _)
-        | ConstraintSolverTypesNotInSubsumptionRelation (_, _, _, m, _)
-        | SelfRefObjCtor (_, m) -> Some m
+        | NonRigidTypar(_, _, _, _, _, m)
+        | ConstraintSolverTupleDiffLengths(_, _, _, _, m, _)
+        | ConstraintSolverInfiniteTypes(_, _, _, _, m, _)
+        | ConstraintSolverMissingConstraint(_, _, _, m, _)
+        | ConstraintSolverNullnessWarningEquivWithTypes(_, _, _, _, _, m, _)
+        | ConstraintSolverNullnessWarningWithTypes(_, _, _, _, _, m, _)
+        | ConstraintSolverNullnessWarningWithType(_, _, _, m, _)
+        | ConstraintSolverNullnessWarning(_, m, _)
+        | ConstraintSolverTypesNotInEqualityRelation(_, _, _, m, _, _)
+        | ConstraintSolverError(_, m, _)
+        | ConstraintSolverTypesNotInSubsumptionRelation(_, _, _, m, _)
+        | SelfRefObjCtor(_, m) -> Some m
 
         | NotAFunction(_, _, mfun, _) -> Some mfun
 
@@ -685,7 +685,7 @@ type Exception with
             if m.StartLine <> m2.StartLine then
                 os.AppendString(SeeAlsoE().Format(stringOfRange m))
 
-        | ConstraintSolverNullnessWarningEquivWithTypes (denv, ty1, ty2, _nullness1, _nullness2, m, m2) ->
+        | ConstraintSolverNullnessWarningEquivWithTypes(denv, ty1, ty2, _nullness1, _nullness2, m, m2) ->
 
             // Turn on nullness annotations for messages about nullness
             let denv =
@@ -701,7 +701,7 @@ type Exception with
             if m.StartLine <> m2.StartLine then
                 os.Append(SeeAlsoE().Format(stringOfRange m)) |> ignore
 
-        | ConstraintSolverNullnessWarningWithTypes (denv, ty1, ty2, _nullness1, _nullness2, m, m2) ->
+        | ConstraintSolverNullnessWarningWithTypes(denv, ty1, ty2, _nullness1, _nullness2, m, m2) ->
 
             // Turn on nullness annotations for messages about nullness
             let denv =
@@ -716,7 +716,7 @@ type Exception with
             if m.StartLine <> m2.StartLine then
                 os.Append(SeeAlsoE().Format(stringOfRange m)) |> ignore
 
-        | ConstraintSolverNullnessWarningWithType (denv, ty, _, m, m2) ->
+        | ConstraintSolverNullnessWarningWithType(denv, ty, _, m, m2) ->
 
             // Turn on nullness annotations for messages about nullness
             let denv =
@@ -730,13 +730,13 @@ type Exception with
             if m.StartLine <> m2.StartLine then
                 os.Append(SeeAlsoE().Format(stringOfRange m)) |> ignore
 
-        | ConstraintSolverNullnessWarning (msg, m, m2) ->
+        | ConstraintSolverNullnessWarning(msg, m, m2) ->
             os.Append(ConstraintSolverNullnessWarningE().Format(msg)) |> ignore
 
             if m.StartLine <> m2.StartLine then
                 os.AppendString(SeeAlsoE().Format(stringOfRange m2))
 
-        | ConstraintSolverMissingConstraint (denv, tpr, tpc, m, m2) ->
+        | ConstraintSolverMissingConstraint(denv, tpr, tpc, m, m2) ->
             os.AppendString(
                 ConstraintSolverMissingConstraintE()
                     .Format(NicePrint.stringOfTyparConstraint denv (tpr, tpc))
diff --git a/src/Compiler/Driver/GraphChecking/FileContentMapping.fs b/src/Compiler/Driver/GraphChecking/FileContentMapping.fs
index 7ef16b33481..8ece68bd4bb 100644
--- a/src/Compiler/Driver/GraphChecking/FileContentMapping.fs
+++ b/src/Compiler/Driver/GraphChecking/FileContentMapping.fs
@@ -245,9 +245,9 @@ let visitSynType (t: SynType) : FileContentEntry list =
         | SynType.AnonRecd(fields = fields) ->
             let continuations = List.map (snd >> visit) fields
             Continuation.concatenate continuations continuation
-        | SynType.Array (elementType = elementType) -> visit elementType continuation
-        | SynType.WithNull (innerType = innerType) -> visit innerType continuation
-        | SynType.Fun (argType, returnType, _, _) ->
+        | SynType.Array(elementType = elementType) -> visit elementType continuation
+        | SynType.WithNull(innerType = innerType) -> visit innerType continuation
+        | SynType.Fun(argType, returnType, _, _) ->
             let continuations = List.map visit [ argType; returnType ]
             Continuation.concatenate continuations continuation
         | SynType.Var _ -> continuation []
@@ -258,8 +258,8 @@ let visitSynType (t: SynType) : FileContentEntry list =
         | SynType.MeasurePower(baseMeasure = baseMeasure) -> visit baseMeasure continuation
         | SynType.StaticConstant _ -> continuation []
         | SynType.StaticConstantNull _ -> continuation []
-        | SynType.StaticConstantExpr (expr, _) -> continuation (visitSynExpr expr)
-        | SynType.StaticConstantNamed (ident, value, _) ->
+        | SynType.StaticConstantExpr(expr, _) -> continuation (visitSynExpr expr)
+        | SynType.StaticConstantNamed(ident, value, _) ->
             let continuations = List.map visit [ ident; value ]
             Continuation.concatenate continuations continuation
         | SynType.Paren(innerType, _) -> visit innerType continuation
diff --git a/src/Compiler/Interactive/fsi.fs b/src/Compiler/Interactive/fsi.fs
index f0e1e454785..62dd094e20c 100644
--- a/src/Compiler/Interactive/fsi.fs
+++ b/src/Compiler/Interactive/fsi.fs
@@ -1559,7 +1559,7 @@ let rec ConvReflectionTypeToILType (reflectionTy: Type) =
 
             if
                 ctors.Length = 1
-                && not (isNull (box (ctors[ 0 ].GetCustomAttribute())))
+                && not (isNull (box (ctors[0].GetCustomAttribute())))
                 && not ctors[0].IsPublic
                 && IsCompilerGeneratedName reflectionTy.Name
             then
@@ -3525,7 +3525,7 @@ type FsiStdinLexerProvider
                         fprintfn fsiConsoleOutput.Out "End of file from TextReader.ReadLine"
 
                     0
-                | Some (NonNull input) ->
+                | Some(NonNull input) ->
                     let input = nonNull input + "\n"
 
                     if input.Length > len then
diff --git a/src/Compiler/Service/ServiceParseTreeWalk.fs b/src/Compiler/Service/ServiceParseTreeWalk.fs
index 68a3989df48..e18c3cff03f 100644
--- a/src/Compiler/Service/ServiceParseTreeWalk.fs
+++ b/src/Compiler/Service/ServiceParseTreeWalk.fs
@@ -765,21 +765,21 @@ module SyntaxTraversal =
                 let path = SyntaxNode.SynType ty :: origPath
 
                 match ty with
-                | SynType.App (typeName, _, typeArgs, _, _, _, _)
-                | SynType.LongIdentApp (typeName, _, _, typeArgs, _, _, _) -> typeName :: typeArgs |> List.tryPick (traverseSynType path)
-                | SynType.Fun (argType = ty1; returnType = ty2) -> [ ty1; ty2 ] |> List.tryPick (traverseSynType path)
-                | SynType.MeasurePower (ty, _, _)
-                | SynType.HashConstraint (ty, _)
-                | SynType.WithNull (ty, _, _)
-                | SynType.WithGlobalConstraints (ty, _, _)
-                | SynType.Array (_, ty, _) -> traverseSynType path ty
-                | SynType.StaticConstantNamed (ty1, ty2, _)
-                | SynType.Or (ty1, ty2, _, _) -> [ ty1; ty2 ] |> List.tryPick (traverseSynType path)
-                | SynType.Tuple (path = segments) -> getTypeFromTuplePath segments |> List.tryPick (traverseSynType path)
-                | SynType.StaticConstantExpr (expr, _) -> traverseSynExpr [] expr
-                | SynType.Paren (innerType = t)
-                | SynType.SignatureParameter (usedType = t) -> traverseSynType path t
-                | SynType.Intersection (types = types) -> List.tryPick (traverseSynType path) types
+                | SynType.App(typeName, _, typeArgs, _, _, _, _)
+                | SynType.LongIdentApp(typeName, _, _, typeArgs, _, _, _) -> typeName :: typeArgs |> List.tryPick (traverseSynType path)
+                | SynType.Fun(argType = ty1; returnType = ty2) -> [ ty1; ty2 ] |> List.tryPick (traverseSynType path)
+                | SynType.MeasurePower(ty, _, _)
+                | SynType.HashConstraint(ty, _)
+                | SynType.WithNull(ty, _, _)
+                | SynType.WithGlobalConstraints(ty, _, _)
+                | SynType.Array(_, ty, _) -> traverseSynType path ty
+                | SynType.StaticConstantNamed(ty1, ty2, _)
+                | SynType.Or(ty1, ty2, _, _) -> [ ty1; ty2 ] |> List.tryPick (traverseSynType path)
+                | SynType.Tuple(path = segments) -> getTypeFromTuplePath segments |> List.tryPick (traverseSynType path)
+                | SynType.StaticConstantExpr(expr, _) -> traverseSynExpr [] expr
+                | SynType.Paren(innerType = t)
+                | SynType.SignatureParameter(usedType = t) -> traverseSynType path t
+                | SynType.Intersection(types = types) -> List.tryPick (traverseSynType path) types
                 | SynType.StaticConstantNull _
                 | SynType.Anon _
                 | SynType.AnonRecd _
diff --git a/src/Compiler/Service/ServiceParsedInputOps.fs b/src/Compiler/Service/ServiceParsedInputOps.fs
index f50dd5e60f7..421ccc3fb0d 100644
--- a/src/Compiler/Service/ServiceParsedInputOps.fs
+++ b/src/Compiler/Service/ServiceParsedInputOps.fs
@@ -631,16 +631,16 @@ module ParsedInput =
 
         and walkTypeConstraint cx =
             match cx with
-            | SynTypeConstraint.WhereTyparDefaultsToType (t1, t2, _) -> walkTypar t1 |> Option.orElseWith (fun () -> walkType t2)
-            | SynTypeConstraint.WhereTyparIsValueType (t, _) -> walkTypar t
-            | SynTypeConstraint.WhereTyparIsReferenceType (t, _) -> walkTypar t
-            | SynTypeConstraint.WhereTyparIsUnmanaged (t, _) -> walkTypar t
-            | SynTypeConstraint.WhereTyparSupportsNull (t, _) -> walkTypar t
-            | SynTypeConstraint.WhereTyparNotSupportsNull (t, _) -> walkTypar t
-            | SynTypeConstraint.WhereTyparIsComparable (t, _) -> walkTypar t
-            | SynTypeConstraint.WhereTyparIsEquatable (t, _) -> walkTypar t
-            | SynTypeConstraint.WhereTyparSubtypeOfType (t, ty, _) -> walkTypar t |> Option.orElseWith (fun () -> walkType ty)
-            | SynTypeConstraint.WhereTyparSupportsMember (TypesForTypar ts, sign, _) ->
+            | SynTypeConstraint.WhereTyparDefaultsToType(t1, t2, _) -> walkTypar t1 |> Option.orElseWith (fun () -> walkType t2)
+            | SynTypeConstraint.WhereTyparIsValueType(t, _) -> walkTypar t
+            | SynTypeConstraint.WhereTyparIsReferenceType(t, _) -> walkTypar t
+            | SynTypeConstraint.WhereTyparIsUnmanaged(t, _) -> walkTypar t
+            | SynTypeConstraint.WhereTyparSupportsNull(t, _) -> walkTypar t
+            | SynTypeConstraint.WhereTyparNotSupportsNull(t, _) -> walkTypar t
+            | SynTypeConstraint.WhereTyparIsComparable(t, _) -> walkTypar t
+            | SynTypeConstraint.WhereTyparIsEquatable(t, _) -> walkTypar t
+            | SynTypeConstraint.WhereTyparSubtypeOfType(t, ty, _) -> walkTypar t |> Option.orElseWith (fun () -> walkType ty)
+            | SynTypeConstraint.WhereTyparSupportsMember(TypesForTypar ts, sign, _) ->
                 List.tryPick walkType ts |> Option.orElseWith (fun () -> walkMemberSig sign)
             | SynTypeConstraint.WhereTyparIsEnum(t, ts, _) -> walkTypar t |> Option.orElseWith (fun () -> List.tryPick walkType ts)
             | SynTypeConstraint.WhereTyparIsDelegate(t, ts, _) -> walkTypar t |> Option.orElseWith (fun () -> List.tryPick walkType ts)
@@ -694,21 +694,21 @@ module ParsedInput =
                     ifPosInRange ident.Range (fun _ -> Some EntityKind.Type)
                 with _ ->
                     None
-            | SynType.App (ty, _, types, _, _, _, _) -> walkType ty |> Option.orElseWith (fun () -> List.tryPick walkType types)
-            | SynType.LongIdentApp (_, _, _, types, _, _, _) -> List.tryPick walkType types
-            | SynType.Tuple (path = segments) -> getTypeFromTuplePath segments |> List.tryPick walkType
-            | SynType.Array (_, t, _) -> walkType t
-            | SynType.Fun (argType = t1; returnType = t2) -> walkType t1 |> Option.orElseWith (fun () -> walkType t2)
-            | SynType.WithGlobalConstraints (t, _, _) -> walkType t
-            | SynType.WithNull (t, _, _)
-            | SynType.HashConstraint (t, _) -> walkType t
-            | SynType.Or (t1, t2, _, _) -> walkType t1 |> Option.orElseWith (fun () -> walkType t2)
-            | SynType.MeasurePower (t, _, _) -> walkType t
-            | SynType.Paren (t, _)
-            | SynType.SignatureParameter (usedType = t) -> walkType t
-            | SynType.StaticConstantExpr (e, _) -> walkExpr e
-            | SynType.StaticConstantNamed (ident, value, _) -> List.tryPick walkType [ ident; value ]
-            | SynType.Intersection (types = types) -> List.tryPick walkType types
+            | SynType.App(ty, _, types, _, _, _, _) -> walkType ty |> Option.orElseWith (fun () -> List.tryPick walkType types)
+            | SynType.LongIdentApp(_, _, _, types, _, _, _) -> List.tryPick walkType types
+            | SynType.Tuple(path = segments) -> getTypeFromTuplePath segments |> List.tryPick walkType
+            | SynType.Array(_, t, _) -> walkType t
+            | SynType.Fun(argType = t1; returnType = t2) -> walkType t1 |> Option.orElseWith (fun () -> walkType t2)
+            | SynType.WithGlobalConstraints(t, _, _) -> walkType t
+            | SynType.WithNull(t, _, _)
+            | SynType.HashConstraint(t, _) -> walkType t
+            | SynType.Or(t1, t2, _, _) -> walkType t1 |> Option.orElseWith (fun () -> walkType t2)
+            | SynType.MeasurePower(t, _, _) -> walkType t
+            | SynType.Paren(t, _)
+            | SynType.SignatureParameter(usedType = t) -> walkType t
+            | SynType.StaticConstantExpr(e, _) -> walkExpr e
+            | SynType.StaticConstantNamed(ident, value, _) -> List.tryPick walkType [ ident; value ]
+            | SynType.Intersection(types = types) -> List.tryPick walkType types
             | SynType.StaticConstantNull _
             | SynType.Anon _
             | SynType.AnonRecd _
@@ -1771,15 +1771,15 @@ module ParsedInput =
 
         and walkTypeConstraint cx =
             match cx with
-            | SynTypeConstraint.WhereTyparIsValueType (t, _)
-            | SynTypeConstraint.WhereTyparIsReferenceType (t, _)
-            | SynTypeConstraint.WhereTyparIsUnmanaged (t, _)
-            | SynTypeConstraint.WhereTyparSupportsNull (t, _)
-            | SynTypeConstraint.WhereTyparNotSupportsNull (t, _)
-            | SynTypeConstraint.WhereTyparIsComparable (t, _)
-            | SynTypeConstraint.WhereTyparIsEquatable (t, _) -> walkTypar t
-            | SynTypeConstraint.WhereTyparDefaultsToType (t, ty, _)
-            | SynTypeConstraint.WhereTyparSubtypeOfType (t, ty, _) ->
+            | SynTypeConstraint.WhereTyparIsValueType(t, _)
+            | SynTypeConstraint.WhereTyparIsReferenceType(t, _)
+            | SynTypeConstraint.WhereTyparIsUnmanaged(t, _)
+            | SynTypeConstraint.WhereTyparSupportsNull(t, _)
+            | SynTypeConstraint.WhereTyparNotSupportsNull(t, _)
+            | SynTypeConstraint.WhereTyparIsComparable(t, _)
+            | SynTypeConstraint.WhereTyparIsEquatable(t, _) -> walkTypar t
+            | SynTypeConstraint.WhereTyparDefaultsToType(t, ty, _)
+            | SynTypeConstraint.WhereTyparSubtypeOfType(t, ty, _) ->
                 walkTypar t
                 walkType ty
             | SynTypeConstraint.WhereTyparIsEnum(t, ts, _)
@@ -1834,14 +1834,14 @@ module ParsedInput =
 
         and walkType synType =
             match synType with
-            | SynType.Array (_, t, _)
-            | SynType.HashConstraint (t, _)
-            | SynType.MeasurePower (t, _, _)
-            | SynType.WithNull (t, _, _)
-            | SynType.Paren (t, _)
-            | SynType.SignatureParameter (usedType = t) -> walkType t
-            | SynType.Fun (argType = t1; returnType = t2)
-            | SynType.Or (t1, t2, _, _) ->
+            | SynType.Array(_, t, _)
+            | SynType.HashConstraint(t, _)
+            | SynType.MeasurePower(t, _, _)
+            | SynType.WithNull(t, _, _)
+            | SynType.Paren(t, _)
+            | SynType.SignatureParameter(usedType = t) -> walkType t
+            | SynType.Fun(argType = t1; returnType = t2)
+            | SynType.Or(t1, t2, _, _) ->
                 walkType t1
                 walkType t2
             | SynType.LongIdent ident -> addLongIdentWithDots ident
@@ -1857,7 +1857,7 @@ module ParsedInput =
             | SynType.StaticConstantNamed(ident, value, _) ->
                 walkType ident
                 walkType value
-            | SynType.Intersection (types = types) -> List.iter walkType types
+            | SynType.Intersection(types = types) -> List.iter walkType types
             | SynType.StaticConstantNull _
             | SynType.Anon _
             | SynType.AnonRecd _
diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs
index 6c1c182268f..4b413937cb2 100644
--- a/src/Compiler/SyntaxTree/SyntaxTree.fs
+++ b/src/Compiler/SyntaxTree/SyntaxTree.fs
@@ -471,27 +471,27 @@ type SynType =
 
     member x.Range =
         match x with
-        | SynType.App (range = m)
-        | SynType.LongIdentApp (range = m)
-        | SynType.Tuple (range = m)
-        | SynType.Array (range = m)
-        | SynType.AnonRecd (range = m)
-        | SynType.Fun (range = m)
-        | SynType.Var (range = m)
-        | SynType.Anon (range = m)
-        | SynType.WithGlobalConstraints (range = m)
-        | SynType.StaticConstant (range = m)
-        | SynType.StaticConstantNull (range = m)
-        | SynType.StaticConstantExpr (range = m)
-        | SynType.StaticConstantNamed (range = m)
-        | SynType.HashConstraint (range = m)
-        | SynType.WithNull (range = m)
-        | SynType.MeasurePower (range = m)
-        | SynType.Paren (range = m)
-        | SynType.SignatureParameter (range = m)
-        | SynType.Or (range = m)
-        | SynType.Intersection (range = m)
-        | SynType.FromParseError (range = m) -> m
+        | SynType.App(range = m)
+        | SynType.LongIdentApp(range = m)
+        | SynType.Tuple(range = m)
+        | SynType.Array(range = m)
+        | SynType.AnonRecd(range = m)
+        | SynType.Fun(range = m)
+        | SynType.Var(range = m)
+        | SynType.Anon(range = m)
+        | SynType.WithGlobalConstraints(range = m)
+        | SynType.StaticConstant(range = m)
+        | SynType.StaticConstantNull(range = m)
+        | SynType.StaticConstantExpr(range = m)
+        | SynType.StaticConstantNamed(range = m)
+        | SynType.HashConstraint(range = m)
+        | SynType.WithNull(range = m)
+        | SynType.MeasurePower(range = m)
+        | SynType.Paren(range = m)
+        | SynType.SignatureParameter(range = m)
+        | SynType.Or(range = m)
+        | SynType.Intersection(range = m)
+        | SynType.FromParseError(range = m) -> m
         | SynType.LongIdent lidwd -> lidwd.Range
 
 []

From 5a74640b79ebbf7f8bfa081e3d91677329a3c916 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Tue, 28 Nov 2023 15:05:55 +0100
Subject: [PATCH 35/59] bsl fix

---
 tests/fsharp/typecheck/sigs/neg69.vsbsl | 66 +------------------------
 1 file changed, 2 insertions(+), 64 deletions(-)

diff --git a/tests/fsharp/typecheck/sigs/neg69.vsbsl b/tests/fsharp/typecheck/sigs/neg69.vsbsl
index 238ddb81a26..75e44001573 100644
--- a/tests/fsharp/typecheck/sigs/neg69.vsbsl
+++ b/tests/fsharp/typecheck/sigs/neg69.vsbsl
@@ -95,68 +95,6 @@ To continue using non-conforming indentation, pass the '--strict-indentation-' f
 neg69.fsx(242,1,242,3): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (221:1). Try indenting this further.
 To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7.
 
-neg69.fsx(88,43,88,44): parse error FS1241: Expected type argument or static argument
-
-neg69.fsx(88,44,88,45): parse error FS0010: Unexpected symbol '>' in type definition. Expected '=' or other token.
-
-neg69.fsx(94,5,94,8): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (93:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(94,5,94,8): parse error FS0010: Unexpected keyword 'let' or 'use' in implementation file
-
-neg69.fsx(95,5,95,8): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (94:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(96,5,96,8): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (95:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(98,5,98,11): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(98,19,98,20): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(99,5,99,11): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(100,5,100,11): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(101,5,101,11): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(102,5,102,11): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(104,5,104,14): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(113,1,113,5): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(168,1,168,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(170,1,170,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (168:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(171,1,171,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (170:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(172,1,172,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (171:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(173,1,173,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (172:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(174,1,174,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (173:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(176,1,176,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (174:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(177,1,177,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (176:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(178,1,178,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (177:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(180,1,180,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (178:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(181,1,181,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (180:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(182,1,182,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (181:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(183,1,183,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (182:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(185,1,185,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (183:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(194,1,194,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (185:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(203,1,203,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (194:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(212,1,212,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (203:1). Try indenting this token further or using standard formatting conventions.
-
-neg69.fsx(221,1,221,4): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (212:1). Try indenting this token further or using standard formatting conventions.
+neg69.fsx(87,6,87,12): typecheck error FS0929: This type requires a definition
 
-neg69.fsx(242,1,242,3): parse error FS0058: Possible incorrect indentation: this token is offside of context started at position (221:1). Try indenting this token further or using standard formatting conventions.
+neg69.fsx(87,6,87,12): typecheck error FS0912: This declaration element is not permitted in an augmentation

From f690ab6f70d75d771c78aa71aa60ff1e66096522 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Tue, 28 Nov 2023 16:22:40 +0100
Subject: [PATCH 36/59] il tests update

---
 .../Nullness/AnonRecords.fs.il.net472.bsl     |   1 +
 .../Nullness/AnonRecords.fs.il.netcore.bsl    |  82 ++---------
 .../Nullness/CurriedFunctions.fs.il.bsl       |  94 ++----------
 .../EmittedIL/Nullness/CustomType.fs.il.bsl   |  96 ++-----------
 .../Nullness/ModuleLevelBindings.fs.il.bsl    |  78 +---------
 .../Nullness/ModuleLevelFunctions.fs.il.bsl   |  96 ++-----------
 .../ModuleLevelFunctionsOpt.fs.il.bsl         |  96 ++-----------
 .../Nullness/NullAsTrueValue.fs.il.net472.bsl |   1 +
 .../NullAsTrueValue.fs.il.netcore.bsl         | 134 +++++-------------
 .../Nullness/Records.fs.il.net472.bsl         |   1 +
 .../Nullness/Records.fs.il.netcore.bsl        |  82 ++---------
 .../Nullness/ReferenceDU.fs.il.net472.bsl     |   1 +
 .../Nullness/ReferenceDU.fs.il.netcore.bsl    |  90 ++----------
 .../Nullness/StructDU.fs.il.net472.bsl        |   1 +
 .../Nullness/StructDU.fs.il.netcore.bsl       |  82 ++---------
 15 files changed, 140 insertions(+), 795 deletions(-)

diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.net472.bsl
index cfed4707176..66aa48e83f6 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.net472.bsl
@@ -776,6 +776,7 @@
 .class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field public uint8[] NullableFlags
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.netcore.bsl
index 1f5eb583c76..4fef0ae7baf 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.netcore.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.netcore.bsl
@@ -26,7 +26,7 @@
        extends [runtime]System.Object
 {
   .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
-  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
   .method public specialname static int32 
           get_justInt() cil managed
   {
@@ -62,7 +62,7 @@
           giveMeA() cil managed
   {
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 04 00 00 00 01 02 02 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 04 00 00 00 01 02 02 02 00 00 ) 
     
     .maxstack  8
     IL_0000:  call       string MyTestModule::get_maybeString()
@@ -92,7 +92,7 @@
           giveMeC() cil managed
   {
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 04 00 00 00 01 02 02 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 04 00 00 00 01 02 02 02 00 00 ) 
     
     .maxstack  8
     IL_0000:  call       string MyTestModule::get_maybeString()
@@ -110,13 +110,13 @@
   } 
   .property string maybeString()
   {
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .get string MyTestModule::get_maybeString()
   } 
   .property class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1
           maybeListOfMaybeString()
   {
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) 
     .get class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 MyTestModule::get_maybeListOfMaybeString()
   } 
@@ -125,9 +125,9 @@
 .class private abstract auto ansi sealed ''.$MyTestModule
        extends [runtime]System.Object
 {
-  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
   .field static assembly initonly class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 maybeListOfMaybeString@5
-  .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
   .field static assembly int32 init@
   .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
@@ -158,7 +158,7 @@
 {
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) 
-  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
   .field private !'j__TPar' A@
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
@@ -680,72 +680,6 @@
   } 
 } 
 
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8[] NullableFlags
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 scalarByteValue) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldc.i4.1
-    IL_0008:  newarr     [runtime]System.Byte
-    IL_000d:  dup
-    IL_000e:  ldc.i4.0
-    IL_000f:  ldarg.1
-    IL_0010:  stelem.i1
-    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_0016:  ret
-  } 
-
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8[] NullableFlags) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_000d:  ret
-  } 
-
-} 
-
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8 Flag
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 Flag) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
-    IL_000d:  ret
-  } 
-
-} 
-
 
 
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.bsl
index e785503e5b7..5d449672a57 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.bsl
@@ -26,11 +26,11 @@
        extends [runtime]System.Object
 {
   .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
-  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
   .class auto ansi serializable sealed nested assembly beforefieldinit partiallyAplied@8
          extends class [FSharp.Core]Microsoft.FSharp.Core.OptimizedClosures/FSharpFunc`3>
   {
-    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .field public string propperString
     .method assembly specialname rtspecialname 
             instance void  .ctor(string propperString) cil managed
@@ -58,8 +58,8 @@
       IL_0006:  ldarg.1
       IL_0007:  ldarg.2
       IL_0008:  newobj     instance void class [runtime]System.Tuple`3::.ctor(!0,
-                                                                                                    !1,
-                                                                                                    !2)
+                                                                                                          !1,
+                                                                                                          !2)
       IL_000d:  ret
     } 
 
@@ -73,17 +73,17 @@
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 
                                                                                                                     00 00 00 00 ) 
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 01 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 01 00 00 ) 
     .param [1]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     
     .maxstack  8
     IL_0000:  ldarg.0
     IL_0001:  ldarg.1
     IL_0002:  ldarg.2
     IL_0003:  newobj     instance void class [runtime]System.Tuple`3::.ctor(!0,
-                                                                                                  !1,
-                                                                                                  !2)
+                                                                                                        !1,
+                                                                                                        !2)
     IL_0008:  ret
   } 
 
@@ -91,7 +91,7 @@
           partiallyAplied(string propperString) cil managed
   {
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 06 00 00 00 01 01 01 01 02 01 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 06 00 00 00 01 01 01 01 02 01 00 00 ) 
     
     .maxstack  8
     IL_0000:  ldarg.0
@@ -108,15 +108,15 @@
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 03 00 00 00 01 00 00 00 01 00 
                                                                                                                     00 00 00 00 ) 
     .param type a 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
     .param type b 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .param type c 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
     .param type d 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
     .param type e 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
     
     .maxstack  8
     IL_0000:  ldarg.1
@@ -130,72 +130,6 @@
 {
 } 
 
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8[] NullableFlags
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 scalarByteValue) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldc.i4.1
-    IL_0008:  newarr     [runtime]System.Byte
-    IL_000d:  dup
-    IL_000e:  ldc.i4.0
-    IL_000f:  ldarg.1
-    IL_0010:  stelem.i1
-    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_0016:  ret
-  } 
-
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8[] NullableFlags) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_000d:  ret
-  } 
-
-} 
-
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8 Flag
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 Flag) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
-    IL_000d:  ret
-  } 
-
-} 
-
 
 
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.bsl
index 93c51018c48..8918c6939f0 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.bsl
@@ -31,14 +31,14 @@
   {
     .custom instance void [runtime]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 )                      
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) 
-    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .field static assembly string uglyGlobalMutableString
     .field static assembly string uglyGlobalMutableNullableString
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .field static assembly class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 dict
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 02 00 00 ) 
     .field assembly string Nullable@
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .field assembly string NonNullable@
     .field assembly int32 JustSomeInt@
     .field static assembly int32 init@6
@@ -47,7 +47,7 @@
                                  string y) cil managed
     {
       .param [1]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldarg.0
@@ -72,7 +72,7 @@
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldarg.0
@@ -107,7 +107,7 @@
     .method public static string  GiveMeNull() cil managed
     {
       .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldnull
@@ -143,7 +143,7 @@
             GetThisOrNull() cil managed
     {
       .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldnull
@@ -154,9 +154,9 @@
             instance string  get_Item(string index) cil managed
     {
       .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       .param [1]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  volatile.
@@ -179,9 +179,9 @@
                                     string 'value') cil managed
     {
       .param [1]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       .param [2]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  volatile.
@@ -223,7 +223,7 @@
 
     .property instance string Nullable()
     {
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       .get instance string MyTestModule/Myassembly::get_Nullable()
     } 
     .property instance string NonNullable()
@@ -236,7 +236,7 @@
     } 
     .property instance string Item(string)
     {
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       .set instance void MyTestModule/Myassembly::set_Item(string,
                                                              string)
       .get instance string MyTestModule/Myassembly::get_Item(string)
@@ -248,7 +248,7 @@
 .class private abstract auto ansi sealed ''.$MyTestModule
        extends [runtime]System.Object
 {
-  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
   .field static assembly int32 init@
   .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
@@ -278,72 +278,6 @@
 
 } 
 
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8[] NullableFlags
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 scalarByteValue) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldc.i4.1
-    IL_0008:  newarr     [runtime]System.Byte
-    IL_000d:  dup
-    IL_000e:  ldc.i4.0
-    IL_000f:  ldarg.1
-    IL_0010:  stelem.i1
-    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_0016:  ret
-  } 
-
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8[] NullableFlags) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_000d:  ret
-  } 
-
-} 
-
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8 Flag
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 Flag) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
-    IL_000d:  ret
-  } 
-
-} 
-
 
 
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.bsl
index b4741b88b22..3878ca14c07 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.bsl
@@ -26,9 +26,9 @@
        extends [runtime]System.Object
 {
   .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
-  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
   .field public static literal string nullableLiteral = ""
-  .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
   .custom instance void [FSharp.Core]Microsoft.FSharp.Core.LiteralAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
   .method public specialname static string 
@@ -113,12 +113,12 @@
   } 
   .property string nullableStringField()
   {
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .get string MyTestModule::get_nullableStringField()
   } 
   .property string nullableMutableStringField()
   {
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) 
     .set void MyTestModule::set_nullableMutableStringField(string)
     .get string MyTestModule::get_nullableMutableStringField()
@@ -137,9 +137,9 @@
 .class private abstract auto ansi sealed ''.$MyTestModule
        extends [runtime]System.Object
 {
-  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
   .field static assembly string nullableMutableStringField@6
-  .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
   .field static assembly int32 init@
   .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
@@ -157,72 +157,6 @@
 
 } 
 
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8[] NullableFlags
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 scalarByteValue) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldc.i4.1
-    IL_0008:  newarr     [runtime]System.Byte
-    IL_000d:  dup
-    IL_000e:  ldc.i4.0
-    IL_000f:  ldarg.1
-    IL_0010:  stelem.i1
-    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_0016:  ret
-  } 
-
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8[] NullableFlags) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_000d:  ret
-  } 
-
-} 
-
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8 Flag
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 Flag) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
-    IL_000d:  ret
-  } 
-
-} 
-
 
 
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.bsl
index 0860bb96bd6..f3e3c40331a 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.bsl
@@ -26,7 +26,7 @@
        extends [runtime]System.Object
 {
   .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
-  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
   .method public static string  nonNullableInputOutputFunc(string x) cil managed
   {
     
@@ -38,9 +38,9 @@
   .method public static string  nullableStringInputOutputFunc(string x) cil managed
   {
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .param [1]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     
     .maxstack  8
     IL_0000:  ldarg.0
@@ -68,9 +68,9 @@
           genericValueTypeTest(valuetype [runtime]System.ValueTuple`6 x) cil managed
   {
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
     .param [1]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
     
     .maxstack  8
     IL_0000:  ldarg.0
@@ -86,9 +86,9 @@
                              int32 x_5) cil managed
   {
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
     .param [2]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     
     .maxstack  8
     .locals init (class [runtime]System.Tuple`6 V_0)
@@ -99,11 +99,11 @@
     IL_0004:  ldarg.s    x_4
     IL_0006:  ldarg.s    x_5
     IL_0008:  newobj     instance void class [runtime]System.Tuple`6::.ctor(!0,
-                                                                                                                    !1,
-                                                                                                                    !2,
-                                                                                                                    !3,
-                                                                                                                    !4,
-                                                                                                                    !5)
+                                                                                                                          !1,
+                                                                                                                          !2,
+                                                                                                                          !3,
+                                                                                                                          !4,
+                                                                                                                          !5)
     IL_000d:  stloc.0
     IL_000e:  ldloc.0
     IL_000f:  ret
@@ -113,9 +113,9 @@
           nestedGenericsTest(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> x) cil managed
   {
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .param [1]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     
     .maxstack  8
     IL_0000:  ldarg.0
@@ -127,7 +127,7 @@
   {
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
     .param [2]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     
     .maxstack  8
     IL_0000:  ldc.i4.s   42
@@ -141,72 +141,6 @@
 {
 } 
 
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8[] NullableFlags
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 scalarByteValue) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldc.i4.1
-    IL_0008:  newarr     [runtime]System.Byte
-    IL_000d:  dup
-    IL_000e:  ldc.i4.0
-    IL_000f:  ldarg.1
-    IL_0010:  stelem.i1
-    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_0016:  ret
-  } 
-
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8[] NullableFlags) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_000d:  ret
-  } 
-
-} 
-
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8 Flag
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 Flag) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
-    IL_000d:  ret
-  } 
-
-} 
-
 
 
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.bsl
index 6ffc03c1573..f97a7c36bc5 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.bsl
@@ -26,7 +26,7 @@
        extends [runtime]System.Object
 {
   .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
-  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
   .method public static string  nonNullableInputOutputFunc(string x) cil managed
   {
     
@@ -38,9 +38,9 @@
   .method public static string  nullableStringInputOutputFunc(string x) cil managed
   {
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .param [1]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     
     .maxstack  8
     IL_0000:  ldarg.0
@@ -68,9 +68,9 @@
           genericValueTypeTest(valuetype [runtime]System.ValueTuple`6 x) cil managed
   {
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
     .param [1]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
     
     .maxstack  8
     IL_0000:  ldarg.0
@@ -86,9 +86,9 @@
                              int32 x_5) cil managed
   {
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
     .param [2]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     
     .maxstack  8
     IL_0000:  ldarg.0
@@ -98,11 +98,11 @@
     IL_0004:  ldarg.s    x_4
     IL_0006:  ldarg.s    x_5
     IL_0008:  newobj     instance void class [runtime]System.Tuple`6::.ctor(!0,
-                                                                                                                    !1,
-                                                                                                                    !2,
-                                                                                                                    !3,
-                                                                                                                    !4,
-                                                                                                                    !5)
+                                                                                                                          !1,
+                                                                                                                          !2,
+                                                                                                                          !3,
+                                                                                                                          !4,
+                                                                                                                          !5)
     IL_000d:  ret
   } 
 
@@ -110,9 +110,9 @@
           nestedGenericsTest(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> x) cil managed
   {
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .param [1]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     
     .maxstack  8
     IL_0000:  ldarg.0
@@ -124,7 +124,7 @@
   {
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
     .param [2]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     
     .maxstack  8
     IL_0000:  ldc.i4.s   42
@@ -138,72 +138,6 @@
 {
 } 
 
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8[] NullableFlags
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 scalarByteValue) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldc.i4.1
-    IL_0008:  newarr     [runtime]System.Byte
-    IL_000d:  dup
-    IL_000e:  ldc.i4.0
-    IL_000f:  ldarg.1
-    IL_0010:  stelem.i1
-    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_0016:  ret
-  } 
-
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8[] NullableFlags) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_000d:  ret
-  } 
-
-} 
-
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8 Flag
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 Flag) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
-    IL_000d:  ret
-  } 
-
-} 
-
 
 
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl
index 7c42b07d649..b87de0f1315 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl
@@ -970,6 +970,7 @@
 .class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field public uint8[] NullableFlags
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl
index 8520df5ca9f..e7c127ead88 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl
@@ -26,25 +26,25 @@
        extends [runtime]System.Object
 {
   .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
-  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
   .class auto autochar serializable sealed nested public beforefieldinit MyNullableOption`1
          extends [runtime]System.Object
   {
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationRepresentationAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilationRepresentationFlags) = ( 01 00 08 00 00 00 00 00 ) 
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
     .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
                                                                                                          61 79 28 29 2C 6E 71 7D 00 00 )                   
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
-    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .param type T 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .class abstract auto ansi sealed nested public Tags
            extends [runtime]System.Object
     {
       .param type T 
-        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+        .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       .field public static literal int32 MyNone = int32(0x00000000)
       .field public static literal int32 MySome = int32(0x00000001)
     } 
@@ -75,7 +75,7 @@
       .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                   int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
       .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldnull
@@ -173,7 +173,7 @@
     .property class TestModule/MyNullableOption`1
             MyNone()
     {
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
@@ -193,21 +193,21 @@
   .class auto autochar serializable sealed nested public beforefieldinit MyOptionWhichCannotHaveNullInTheInside`1
          extends [runtime]System.Object
   {
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationRepresentationAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilationRepresentationFlags) = ( 01 00 08 00 00 00 00 00 ) 
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
     .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
                                                                                                          61 79 28 29 2C 6E 71 7D 00 00 )                   
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
-    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .param type T 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .class abstract auto ansi sealed nested public Tags
            extends [runtime]System.Object
     {
       .param type T 
-        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+        .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
       .field public static literal int32 MyNotNullNone = int32(0x00000000)
       .field public static literal int32 MyNotNullSome = int32(0x00000001)
     } 
@@ -239,7 +239,7 @@
       .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                   int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
       .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldnull
@@ -338,7 +338,7 @@
     .property class TestModule/MyOptionWhichCannotHaveNullInTheInside`1
             MyNotNullNone()
     {
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
@@ -364,14 +364,14 @@
     .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
                                                                                                          61 79 28 29 2C 6E 71 7D 00 00 )                   
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
-    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .param type T 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .class abstract auto ansi sealed nested public Tags
            extends [runtime]System.Object
     {
       .param type T 
-        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+        .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
       .field public static literal int32 MyStructNone = int32(0x00000000)
       .field public static literal int32 MyStructSome = int32(0x00000001)
     } 
@@ -431,9 +431,9 @@
       .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                   int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
       .param [1]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
       .param [3]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  5
       .locals init (valuetype TestModule/MyStructOption`1 V_0)
@@ -501,7 +501,7 @@
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldarg.0
@@ -515,7 +515,7 @@
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldarg.0
@@ -529,7 +529,7 @@
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldarg.0
@@ -543,7 +543,7 @@
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldarg.0
@@ -635,14 +635,14 @@
       .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                   int32,
                                                                                                   int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .get instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> TestModule/MyStructOption`1::get_nestedGenericField()
     } 
     .property instance string notNullField2()
     {
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                   int32,
                                                                                                   int32) = ( 01 00 04 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
@@ -655,14 +655,14 @@
       .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                   int32,
                                                                                                   int32) = ( 01 00 04 00 00 00 01 00 00 00 02 00 00 00 00 00 ) 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .get instance string TestModule/MyStructOption`1::get_canBeNullField()
     } 
     .property instance !T notNullField1()
     {
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                   int32,
                                                                                                   int32) = ( 01 00 04 00 00 00 01 00 00 00 03 00 00 00 00 00 ) 
@@ -678,9 +678,9 @@
   {
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
     .param type a 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .param type b 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
     
     .maxstack  4
     .locals init (class TestModule/MyNullableOption`1 V_0,
@@ -714,9 +714,9 @@
   {
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
     .param type a 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .param type b 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     
     .maxstack  4
     .locals init (class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 V_0,
@@ -750,13 +750,13 @@
   {
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
     .param type a 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .param type b 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
     .param [2]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
     
     .maxstack  7
     .locals init (valuetype TestModule/MyStructOption`1 V_0,
@@ -808,72 +808,6 @@
 {
 } 
 
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8[] NullableFlags
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 scalarByteValue) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldc.i4.1
-    IL_0008:  newarr     [runtime]System.Byte
-    IL_000d:  dup
-    IL_000e:  ldc.i4.0
-    IL_000f:  ldarg.1
-    IL_0010:  stelem.i1
-    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_0016:  ret
-  } 
-
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8[] NullableFlags) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_000d:  ret
-  } 
-
-} 
-
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8 Flag
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 Flag) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
-    IL_000d:  ret
-  } 
-
-} 
-
 
 
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.net472.bsl
index ce45234c3e9..709a072afd7 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.net472.bsl
@@ -390,6 +390,7 @@
 .class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field public uint8[] NullableFlags
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.netcore.bsl
index b29b5667144..8858ce8beac 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.netcore.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.netcore.bsl
@@ -26,20 +26,20 @@
        extends [runtime]System.Object
 {
   .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
-  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
   .class auto ansi serializable sealed nested public beforefieldinit MyRecord`3
          extends [runtime]System.Object
   {
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) 
-    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .param type X 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
     .param type Y 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .param type Z 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .field assembly int32 JustInt@
     .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
     .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
@@ -52,7 +52,7 @@
     .field assembly string NullableString@
     .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
     .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .field assembly !X GenericNormalField@
     .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
     .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
@@ -261,7 +261,7 @@
           createAnInstance() cil managed
   {
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 01 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 01 00 00 ) 
     
     .maxstack  9
     IL_0000:  ldc.i4.s   42
@@ -284,7 +284,7 @@
 
   .property string maybeString()
   {
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .get string MyTestModule::get_maybeString()
   } 
 } 
@@ -294,72 +294,6 @@
 {
 } 
 
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8[] NullableFlags
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 scalarByteValue) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldc.i4.1
-    IL_0008:  newarr     [runtime]System.Byte
-    IL_000d:  dup
-    IL_000e:  ldc.i4.0
-    IL_000f:  ldarg.1
-    IL_0010:  stelem.i1
-    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_0016:  ret
-  } 
-
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8[] NullableFlags) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_000d:  ret
-  } 
-
-} 
-
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8 Flag
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 Flag) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
-    IL_000d:  ret
-  } 
-
-} 
-
 
 
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.net472.bsl
index d84066219d8..8766a7a551b 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.net472.bsl
@@ -702,6 +702,7 @@
 .class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field public uint8[] NullableFlags
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.netcore.bsl
index da1235dd5eb..c56367b7157 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.netcore.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.netcore.bsl
@@ -31,7 +31,7 @@
        extends [runtime]System.Object
 {
   .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
-  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
   .class abstract auto autochar serializable nested public beforefieldinit MyDu
          extends [runtime]System.Object
   {
@@ -40,7 +40,7 @@
     .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
                                                                                                          61 79 28 29 2C 6E 71 7D 00 00 )                   
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
-    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .class abstract auto ansi sealed nested public Tags
            extends [runtime]System.Object
     {
@@ -52,7 +52,7 @@
     .class auto ansi serializable nested assembly beforefieldinit specialname _JustLabel
            extends MyTestModule/MyDu
     {
-      .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerTypeProxyAttribute::.ctor(class [runtime]System.Type) = ( 01 00 2B 4D 79 54 65 73 74 4D 6F 64 75 6C 65 2B   
                                                                                                                                         4D 79 44 75 2B 5F 4A 75 73 74 4C 61 62 65 6C 40   
                                                                                                                                         44 65 62 75 67 54 79 70 65 50 72 6F 78 79 00 00 ) 
@@ -78,7 +78,7 @@
     .class auto ansi serializable nested public beforefieldinit specialname JustInt
            extends MyTestModule/MyDu
     {
-      .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerTypeProxyAttribute::.ctor(class [runtime]System.Type) = ( 01 00 28 4D 79 54 65 73 74 4D 6F 64 75 6C 65 2B   
                                                                                                                                         4D 79 44 75 2B 4A 75 73 74 49 6E 74 40 44 65 62   
                                                                                                                                         75 67 54 79 70 65 50 72 6F 78 79 00 00 )          
@@ -132,7 +132,7 @@
     .class auto ansi serializable nested public beforefieldinit specialname MaybeString
            extends MyTestModule/MyDu
     {
-      .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerTypeProxyAttribute::.ctor(class [runtime]System.Type) = ( 01 00 2C 4D 79 54 65 73 74 4D 6F 64 75 6C 65 2B   
                                                                                                                                         4D 79 44 75 2B 4D 61 79 62 65 53 74 72 69 6E 67   
                                                                                                                                         40 44 65 62 75 67 54 79 70 65 50 72 6F 78 79 00   
@@ -167,7 +167,7 @@
         .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
         .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
         .param [0]
-        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+        .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
         
         .maxstack  8
         IL_0000:  ldarg.0
@@ -180,7 +180,7 @@
         .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                     int32,
                                                                                                     int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 00 00 00 00 ) 
-        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+        .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
         .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
         .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
         .get instance string MyTestModule/MyDu/MaybeString::get_Item()
@@ -306,7 +306,7 @@
         .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                     int32,
                                                                                                     int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 00 00 00 00 ) 
-        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+        .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
         .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
         .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
         .get instance string MyTestModule/MyDu/MaybeString@DebugTypeProxy::get_Item()
@@ -399,7 +399,7 @@
       .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                   int32) = ( 01 00 08 00 00 00 02 00 00 00 00 00 ) 
       .param [1]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldarg.0
@@ -525,7 +525,7 @@
           createMaybeString(string innerValue) cil managed
   {
     .param [1]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     
     .maxstack  8
     IL_0000:  ldarg.0
@@ -536,9 +536,9 @@
   .method public static string  processNullableDu(class MyTestModule/MyDu x) cil managed
   {
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     .param [1]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     
     .maxstack  5
     .locals init (class MyTestModule/MyDu V_0,
@@ -606,72 +606,6 @@
 {
 } 
 
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8[] NullableFlags
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 scalarByteValue) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldc.i4.1
-    IL_0008:  newarr     [runtime]System.Byte
-    IL_000d:  dup
-    IL_000e:  ldc.i4.0
-    IL_000f:  ldarg.1
-    IL_0010:  stelem.i1
-    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_0016:  ret
-  } 
-
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8[] NullableFlags) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_000d:  ret
-  } 
-
-} 
-
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8 Flag
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 Flag) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
-    IL_000d:  ret
-  } 
-
-} 
-
 
 
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.net472.bsl
index f2b77a10594..22600dd10f1 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.net472.bsl
@@ -504,6 +504,7 @@
 .class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field public uint8[] NullableFlags
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.netcore.bsl
index 03597845da5..3832bab72b8 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.netcore.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.netcore.bsl
@@ -26,7 +26,7 @@
        extends [runtime]System.Object
 {
   .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
-  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
   .class sequential autochar serializable sealed nested public beforefieldinit Myassembly
          extends [runtime]System.ValueType
   {
@@ -36,7 +36,7 @@
     .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
                                                                                                          61 79 28 29 2C 6E 71 7D 00 00 )                   
     .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
-    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
     .class abstract auto ansi sealed nested public Tags
            extends [runtime]System.Object
     {
@@ -127,7 +127,7 @@
       .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                   int32) = ( 01 00 08 00 00 00 02 00 00 00 00 00 ) 
       .param [1]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  2
       .locals init (valuetype MyTestModule/Myassembly V_0)
@@ -179,7 +179,7 @@
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldarg.0
@@ -193,7 +193,7 @@
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldarg.0
@@ -286,7 +286,7 @@
     } 
     .property instance string nonNullableString()
     {
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                   int32,
                                                                                                   int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
@@ -299,7 +299,7 @@
       .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                   int32,
                                                                                                   int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 00 00 00 00 ) 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .get instance string MyTestModule/Myassembly::get_nullableString()
@@ -309,7 +309,7 @@
   .method public static string  getVal(valuetype MyTestModule/Myassembly x) cil managed
   {
     .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
     
     .maxstack  3
     .locals init (valuetype MyTestModule/Myassembly V_0,
@@ -342,72 +342,6 @@
 {
 } 
 
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8[] NullableFlags
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 scalarByteValue) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldc.i4.1
-    IL_0008:  newarr     [runtime]System.Byte
-    IL_000d:  dup
-    IL_000e:  ldc.i4.0
-    IL_000f:  ldarg.1
-    IL_0010:  stelem.i1
-    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_0016:  ret
-  } 
-
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8[] NullableFlags) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
-    IL_000d:  ret
-  } 
-
-} 
-
-.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
-       extends [runtime]System.Attribute
-{
-  .field public uint8 Flag
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(uint8 Flag) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
-    IL_000d:  ret
-  } 
-
-} 
-
 
 
 

From ffd65671f42cedd821e5fa386fa0164b90f0f684 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Wed, 29 Nov 2023 11:26:22 +0100
Subject: [PATCH 37/59] fix test

---
 tests/FSharp.Compiler.ComponentTests/Language/DotLambdaTests.fs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/FSharp.Compiler.ComponentTests/Language/DotLambdaTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/DotLambdaTests.fs
index 6dff28ab6a7..9496e4b4b48 100644
--- a/tests/FSharp.Compiler.ComponentTests/Language/DotLambdaTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Language/DotLambdaTests.fs
@@ -89,7 +89,7 @@ let x = "a" |> _.ToString () """
     'string -> 'a'    
 but given a
     'unit -> string'    
-The type 'string' does not match the type 'unit'""" ]
+The type 'unit' does not match the type 'string'""" ]
 
 []
 let ``Underscore Dot Curried Function With Arguments - NonAtomic`` () =

From 0ea09a6d9bbddc4cf89fc24f5f03dcb903a10165 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Wed, 29 Nov 2023 12:42:35 +0100
Subject: [PATCH 38/59] tests fixed

---
 tests/AheadOfTime/Trimming/check.ps1                        | 6 ++++--
 .../Nullness/FunctionArgAsPatternWithNullCase.fs.bsl        | 2 +-
 .../Nullness/GenericFunctionReturnTypeNotStructNull.fs.bsl  | 3 +--
 .../SyntaxTree/Nullness/GenericFunctionTyparNotNull.fs.bsl  | 2 +-
 .../SyntaxTree/Nullness/GenericFunctionTyparNull.fs.bsl     | 2 +-
 tests/service/data/SyntaxTree/Nullness/IntListOrNull.fs.bsl | 4 ++--
 .../SyntaxTree/Nullness/IntListOrNullOrNullOrNull.fs.bsl    | 4 ++--
 .../data/SyntaxTree/Nullness/NullAnnotatedExpression.fs.bsl | 4 ++--
 tests/service/data/SyntaxTree/Nullness/StringOrNull.fs.bsl  | 4 ++--
 .../SyntaxTree/Nullness/StringOrNullInFunctionArg.fs.bsl    | 2 +-
 10 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index 058dd202051..a9312fad0e6 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -38,8 +38,10 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) {
 # NOTE: Trimming now errors out on desktop TFMs, as shown below:
 # error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher.
 
+$expectedForSlefContained = (If ($compressAllMetadata) {300544} Else {288768})
+
 # Check net7.0 trimmed assemblies
-CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len (If ($compressAllMetadata) {300544} Else {288768})
+CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len $expectedForSlefContained
 
 # Check net7.0 trimmed assemblies
-CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net8.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 8822272
+CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net8.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 8821760 
diff --git a/tests/service/data/SyntaxTree/Nullness/FunctionArgAsPatternWithNullCase.fs.bsl b/tests/service/data/SyntaxTree/Nullness/FunctionArgAsPatternWithNullCase.fs.bsl
index 5a519d0f7e5..016adb52e2b 100644
--- a/tests/service/data/SyntaxTree/Nullness/FunctionArgAsPatternWithNullCase.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/FunctionArgAsPatternWithNullCase.fs.bsl
@@ -13,7 +13,7 @@ ImplFile
                     (None,
                      SynValInfo
                        ([[SynArgInfo ([], false, None)]],
-                        SynArgInfo ([], false, None)), None, None),
+                        SynArgInfo ([], false, None)), None),
                   LongIdent
                     (SynLongIdent ([myFunc], [], [None]), None, None,
                      Pats
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericFunctionReturnTypeNotStructNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/GenericFunctionReturnTypeNotStructNull.fs.bsl
index a3a42b1fb1f..d155f74abba 100644
--- a/tests/service/data/SyntaxTree/Nullness/GenericFunctionReturnTypeNotStructNull.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/GenericFunctionReturnTypeNotStructNull.fs.bsl
@@ -10,8 +10,7 @@ ImplFile
                  (None, Normal, false, false, [],
                   PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
                   SynValData
-                    (None, SynValInfo ([[]], SynArgInfo ([], false, None)), None,
-                     None),
+                    (None, SynValInfo ([[]], SynArgInfo ([], false, None)), None),
                   LongIdent
                     (SynLongIdent ([myFunc], [], [None]), None, None,
                      Pats [Paren (Const (Unit, (1,10--1,12)), (1,10--1,12))],
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNotNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNotNull.fs.bsl
index e648c231c86..2989025967c 100644
--- a/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNotNull.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNotNull.fs.bsl
@@ -13,7 +13,7 @@ ImplFile
                     (None,
                      SynValInfo
                        ([[SynArgInfo ([], false, Some x)]],
-                        SynArgInfo ([], false, None)), None, None),
+                        SynArgInfo ([], false, None)), None),
                   LongIdent
                     (SynLongIdent ([myFunc], [], [None]), None, None,
                      Pats
diff --git a/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNull.fs.bsl
index cf50c657f30..db83d1ddcbf 100644
--- a/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNull.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/GenericFunctionTyparNull.fs.bsl
@@ -13,7 +13,7 @@ ImplFile
                     (None,
                      SynValInfo
                        ([[SynArgInfo ([], false, Some x)]],
-                        SynArgInfo ([], false, None)), None, None),
+                        SynArgInfo ([], false, None)), None),
                   LongIdent
                     (SynLongIdent ([myFunc], [], [None]), None, None,
                      Pats
diff --git a/tests/service/data/SyntaxTree/Nullness/IntListOrNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/IntListOrNull.fs.bsl
index 3e18b8f3910..38442d6c68e 100644
--- a/tests/service/data/SyntaxTree/Nullness/IntListOrNull.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/IntListOrNull.fs.bsl
@@ -10,8 +10,8 @@ ImplFile
                  (None, Normal, false, false, [],
                   PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
                   SynValData
-                    (None, SynValInfo ([], SynArgInfo ([], false, None)), None,
-                     None), Named (SynIdent (x, None), false, None, (1,4--1,5)),
+                    (None, SynValInfo ([], SynArgInfo ([], false, None)), None),
+                  Named (SynIdent (x, None), false, None, (1,4--1,5)),
                   Some
                     (SynBindingReturnInfo
                        (WithNull
diff --git a/tests/service/data/SyntaxTree/Nullness/IntListOrNullOrNullOrNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/IntListOrNullOrNullOrNull.fs.bsl
index 01b86c58866..e538c6dc34b 100644
--- a/tests/service/data/SyntaxTree/Nullness/IntListOrNullOrNullOrNull.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/IntListOrNullOrNullOrNull.fs.bsl
@@ -10,8 +10,8 @@ ImplFile
                  (None, Normal, false, false, [],
                   PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
                   SynValData
-                    (None, SynValInfo ([], SynArgInfo ([], false, None)), None,
-                     None), Named (SynIdent (x, None), false, None, (1,4--1,5)),
+                    (None, SynValInfo ([], SynArgInfo ([], false, None)), None),
+                  Named (SynIdent (x, None), false, None, (1,4--1,5)),
                   Some
                     (SynBindingReturnInfo
                        (WithNull
diff --git a/tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs.bsl b/tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs.bsl
index ee7ce213156..0b9c6e0da1f 100644
--- a/tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/NullAnnotatedExpression.fs.bsl
@@ -10,8 +10,8 @@ ImplFile
                  (None, Normal, false, false, [],
                   PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
                   SynValData
-                    (None, SynValInfo ([], SynArgInfo ([], false, None)), None,
-                     None), Named (SynIdent (x, None), false, None, (1,4--1,5)),
+                    (None, SynValInfo ([], SynArgInfo ([], false, None)), None),
+                  Named (SynIdent (x, None), false, None, (1,4--1,5)),
                   Some
                     (SynBindingReturnInfo
                        (WithNull
diff --git a/tests/service/data/SyntaxTree/Nullness/StringOrNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/StringOrNull.fs.bsl
index f73e3f6ab3a..e803aeedb1f 100644
--- a/tests/service/data/SyntaxTree/Nullness/StringOrNull.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/StringOrNull.fs.bsl
@@ -10,8 +10,8 @@ ImplFile
                  (None, Normal, false, false, [],
                   PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
                   SynValData
-                    (None, SynValInfo ([], SynArgInfo ([], false, None)), None,
-                     None), Named (SynIdent (x, None), false, None, (1,4--1,5)),
+                    (None, SynValInfo ([], SynArgInfo ([], false, None)), None),
+                  Named (SynIdent (x, None), false, None, (1,4--1,5)),
                   Some
                     (SynBindingReturnInfo
                        (WithNull
diff --git a/tests/service/data/SyntaxTree/Nullness/StringOrNullInFunctionArg.fs.bsl b/tests/service/data/SyntaxTree/Nullness/StringOrNullInFunctionArg.fs.bsl
index c10d17ee85f..f369e771916 100644
--- a/tests/service/data/SyntaxTree/Nullness/StringOrNullInFunctionArg.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/StringOrNullInFunctionArg.fs.bsl
@@ -13,7 +13,7 @@ ImplFile
                     (None,
                      SynValInfo
                        ([[SynArgInfo ([], false, Some x)]],
-                        SynArgInfo ([], false, None)), None, None),
+                        SynArgInfo ([], false, None)), None),
                   LongIdent
                     (SynLongIdent ([myFunc], [], [None]), None, None,
                      Pats

From ef15719ec540088fe21199ccf6edd527526b473d Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Wed, 29 Nov 2023 14:10:00 +0100
Subject: [PATCH 39/59] fantomas

---
 src/Compiler/CodeGen/EraseUnions.fs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Compiler/CodeGen/EraseUnions.fs b/src/Compiler/CodeGen/EraseUnions.fs
index 6f1775487d4..5de5bad1360 100644
--- a/src/Compiler/CodeGen/EraseUnions.fs
+++ b/src/Compiler/CodeGen/EraseUnions.fs
@@ -1393,7 +1393,7 @@ let mkClassUnionDef
                                     |> IlxUnionCaseField)
                         else
                             alt.FieldDefs
-                            
+
                     let fieldsToBeAddedIntoType =
                         fieldDefs
                         |> Array.filter (fun f -> fieldsEmitted.Add(struct (f.LowerName, f.Type)))

From f230a6f55cb15530d87613d4ece4f4643777c9f6 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Thu, 30 Nov 2023 14:14:36 +0100
Subject: [PATCH 40/59] fix tests

---
 src/Compiler/CodeGen/IlxGenSupport.fs         |   2 +-
 tests/AheadOfTime/Trimming/check.ps1          |   4 +-
 .../CCtorDUWithMember01a.fs.il.net472.bsl     |  10 -
 .../Compare05.fsx.il.net472.bsl               |  10 -
 .../Compare06.fsx.il.net472.bsl               |  10 -
 .../Compare07.fsx.il.net472.bsl               |  10 -
 .../Compare10.fsx.il.net472.bsl               |  10 -
 .../Equals04.fsx.il.net472.bsl                |  10 -
 .../Equals05.fsx.il.net472.bsl                |  10 -
 .../Equals06.fsx.il.net472.bsl                |  10 -
 .../Equals09.fsx.il.net472.bsl                |  10 -
 .../Hash05.fsx.il.net472.bsl                  |  10 -
 .../Hash06.fsx.il.net472.bsl                  |  10 -
 .../Hash08.fsx.il.net472.bsl                  |  10 -
 .../Hash09.fsx.il.net472.bsl                  |  10 -
 .../Hash12.fsx.il.net472.bsl                  |  10 -
 .../Inlining/Match01.fs.il.net472.release.bsl |  82 ++--
 .../Match01.fs.il.netcore.release.bsl         |  82 ++--
 .../EmittedIL/Misc/AnonRecd.fs.il.net472.bsl  |  10 -
 .../EqualsOnUnions01.fs.il.net472.release.bsl |  10 -
 .../GeneralizationOnUnions01.fs.il.net472.bsl |  10 -
 .../Nullness/AnonRecords.fs.il.net472.bsl     |   2 +
 .../CurriedFunctions.fs.il.net472.bsl         | 205 ++++++++++
 ...bsl => CurriedFunctions.fs.il.netcore.bsl} |   0
 .../Nullness/CustomType.fs.il.net472.bsl      | 353 ++++++++++++++++++
 ...fs.il.bsl => CustomType.fs.il.netcore.bsl} |   0
 .../ModuleLevelBindings.fs.il.net472.bsl      | 232 ++++++++++++
 ... => ModuleLevelBindings.fs.il.netcore.bsl} |   0
 .../ModuleLevelFunctions.fs.il.net472.bsl     | 216 +++++++++++
 ...=> ModuleLevelFunctions.fs.il.netcore.bsl} |   0
 .../ModuleLevelFunctionsOpt.fs.il.net472.bsl  | 213 +++++++++++
 ...ModuleLevelFunctionsOpt.fs.il.netcore.bsl} |   0
 .../Nullness/NullAsTrueValue.fs.il.net472.bsl |   3 +
 .../Nullness/Records.fs.il.net472.bsl         |   2 +
 .../Nullness/ReferenceDU.fs.il.net472.bsl     |   2 +
 .../Nullness/StructDU.fs.il.net472.bsl        |   3 +
 .../ToplevelModule.fs.il.net472.release.bsl   |  10 -
 .../ToplevelModule60.fs.il.net472.release.bsl |  10 -
 ...ToplevelNamespace.fs.il.net472.release.bsl |  10 -
 ...plevelNamespace60.fs.il.net472.release.bsl |  10 -
 .../SteppingMatch06.fs.il.net472.release.bsl  |  10 -
 .../SteppingMatch07.fs.il.net472.release.bsl  |  10 -
 .../TestFunction16.fs.il.net472.release.bsl   |  10 -
 .../TestFunction17.fs.il.net472.release.bsl   |  10 -
 .../TestFunction21.fs.il.net472.release.bsl   |  10 -
 .../TestFunction24.fs.il.net472.release.bsl   |  10 -
 .../Verify13043.fs.il.release.bsl             | 162 ++++----
 47 files changed, 1382 insertions(+), 451 deletions(-)
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.net472.bsl
 rename tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/{CurriedFunctions.fs.il.bsl => CurriedFunctions.fs.il.netcore.bsl} (100%)
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.net472.bsl
 rename tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/{CustomType.fs.il.bsl => CustomType.fs.il.netcore.bsl} (100%)
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.net472.bsl
 rename tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/{ModuleLevelBindings.fs.il.bsl => ModuleLevelBindings.fs.il.netcore.bsl} (100%)
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.net472.bsl
 rename tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/{ModuleLevelFunctions.fs.il.bsl => ModuleLevelFunctions.fs.il.netcore.bsl} (100%)
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.net472.bsl
 rename tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/{ModuleLevelFunctionsOpt.fs.il.bsl => ModuleLevelFunctionsOpt.fs.il.netcore.bsl} (100%)

diff --git a/src/Compiler/CodeGen/IlxGenSupport.fs b/src/Compiler/CodeGen/IlxGenSupport.fs
index 87787697a00..0c641898f24 100644
--- a/src/Compiler/CodeGen/IlxGenSupport.fs
+++ b/src/Compiler/CodeGen/IlxGenSupport.fs
@@ -149,7 +149,7 @@ let mkLocalPrivateAttributeWithPropertyConstructors
         emptyILTypeDefs,
         mkILProperties (ilElements |> List.collect (fun (_, _, props, _) -> props)),
         emptyILEvents,
-        emptyILCustomAttrs,
+        mkILCustomAttrsFromArray [| g.CompilerGeneratedAttribute |],
         ILTypeInit.BeforeField
     )
 
diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index a9312fad0e6..62856de6383 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -38,10 +38,10 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) {
 # NOTE: Trimming now errors out on desktop TFMs, as shown below:
 # error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher.
 
-$expectedForSlefContained = (If ($compressAllMetadata) {300544} Else {288768})
+$expectedForSelfContained = (If ($compressAllMetadata) {300032} Else {288256 })
 
 # Check net7.0 trimmed assemblies
-CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len $expectedForSlefContained
+CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len $expectedForSelfContained
 
 # Check net7.0 trimmed assemblies
 CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net8.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 8821760 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/CCtorDUWithMember/CCtorDUWithMember01a.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/CCtorDUWithMember/CCtorDUWithMember01a.fs.il.net472.bsl
index 6976f3903b3..5889a709646 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/CCtorDUWithMember/CCtorDUWithMember01a.fs.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/CCtorDUWithMember/CCtorDUWithMember01a.fs.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare05.fsx.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare05.fsx.il.net472.bsl
index aa0bd09cd47..d5f4d938c2c 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare05.fsx.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare05.fsx.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare06.fsx.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare06.fsx.il.net472.bsl
index d0ac3122eaf..22d02cd0117 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare06.fsx.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare06.fsx.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare07.fsx.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare07.fsx.il.net472.bsl
index 7a0ad1d24a3..a81dc1388f6 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare07.fsx.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare07.fsx.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare10.fsx.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare10.fsx.il.net472.bsl
index 5b174e9e701..babfda7c605 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare10.fsx.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Compare10.fsx.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals04.fsx.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals04.fsx.il.net472.bsl
index 99c01217900..76c0676daf2 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals04.fsx.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals04.fsx.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals05.fsx.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals05.fsx.il.net472.bsl
index 8989b79ef7c..a6526ec4888 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals05.fsx.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals05.fsx.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals06.fsx.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals06.fsx.il.net472.bsl
index d2e397fc420..1a742f4cb32 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals06.fsx.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals06.fsx.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals09.fsx.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals09.fsx.il.net472.bsl
index 6c3e3536713..0c2241f8207 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals09.fsx.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals09.fsx.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash05.fsx.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash05.fsx.il.net472.bsl
index 2f776bf1ea5..f69f7d551de 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash05.fsx.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash05.fsx.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash06.fsx.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash06.fsx.il.net472.bsl
index 17cba300caf..9a4b1c85857 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash06.fsx.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash06.fsx.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash08.fsx.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash08.fsx.il.net472.bsl
index 112a12a5ce5..0d5793c8d89 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash08.fsx.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash08.fsx.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash09.fsx.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash09.fsx.il.net472.bsl
index cb835008068..524ef02c298 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash09.fsx.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash09.fsx.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash12.fsx.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash12.fsx.il.net472.bsl
index e631641ad71..2ef3f990cf4 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash12.fsx.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Hash12.fsx.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.net472.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.net472.release.bsl
index 9b90e1ab7d1..6848ff990e2 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.net472.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.net472.release.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
@@ -1120,6 +1110,42 @@
     } 
   } 
 
+  .method public static int32  select1(class assembly/Test1 x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  nop
+    IL_0001:  ldarg.0
+    IL_0002:  call       instance int32 assembly/Test1::get_Tag()
+    IL_0007:  switch     ( 
+                          IL_001c,
+                          IL_0028,
+                          IL_002a,
+                          IL_002c)
+    IL_001c:  ldarg.0
+    IL_001d:  castclass  assembly/Test1/X11
+    IL_0022:  ldfld      int32 assembly/Test1/X11::item
+    IL_0027:  ret
+
+    IL_0028:  ldc.i4.2
+    IL_0029:  ret
+
+    IL_002a:  ldc.i4.3
+    IL_002b:  ret
+
+    IL_002c:  ldc.i4.4
+    IL_002d:  ret
+  } 
+
+  .method public static int32  fm(class assembly/Test1 y) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       int32 assembly::select1(class assembly/Test1)
+    IL_0006:  ret
+  } 
+
   .method assembly static int32  CompareTo$cont@4(class assembly/Test1 this,
                                                   class assembly/Test1 obj,
                                                   class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed
@@ -1389,42 +1415,6 @@
     IL_00fc:  ret
   } 
 
-  .method public static int32  select1(class assembly/Test1 x) cil managed
-  {
-    
-    .maxstack  8
-    IL_0000:  nop
-    IL_0001:  ldarg.0
-    IL_0002:  call       instance int32 assembly/Test1::get_Tag()
-    IL_0007:  switch     ( 
-                          IL_001c,
-                          IL_0028,
-                          IL_002a,
-                          IL_002c)
-    IL_001c:  ldarg.0
-    IL_001d:  castclass  assembly/Test1/X11
-    IL_0022:  ldfld      int32 assembly/Test1/X11::item
-    IL_0027:  ret
-
-    IL_0028:  ldc.i4.2
-    IL_0029:  ret
-
-    IL_002a:  ldc.i4.3
-    IL_002b:  ret
-
-    IL_002c:  ldc.i4.4
-    IL_002d:  ret
-  } 
-
-  .method public static int32  fm(class assembly/Test1 y) cil managed
-  {
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       int32 assembly::select1(class assembly/Test1)
-    IL_0006:  ret
-  } 
-
 } 
 
 .class private abstract auto ansi sealed ''.$assembly
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.netcore.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.netcore.release.bsl
index c6444083260..9cfa59775d0 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.netcore.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.netcore.release.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
@@ -1120,6 +1110,42 @@
     } 
   } 
 
+  .method public static int32  select1(class assembly/Test1 x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  nop
+    IL_0001:  ldarg.0
+    IL_0002:  call       instance int32 assembly/Test1::get_Tag()
+    IL_0007:  switch     ( 
+                          IL_001c,
+                          IL_0028,
+                          IL_002a,
+                          IL_002c)
+    IL_001c:  ldarg.0
+    IL_001d:  castclass  assembly/Test1/X11
+    IL_0022:  ldfld      int32 assembly/Test1/X11::item
+    IL_0027:  ret
+
+    IL_0028:  ldc.i4.2
+    IL_0029:  ret
+
+    IL_002a:  ldc.i4.3
+    IL_002b:  ret
+
+    IL_002c:  ldc.i4.4
+    IL_002d:  ret
+  } 
+
+  .method public static int32  fm(class assembly/Test1 y) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       int32 assembly::select1(class assembly/Test1)
+    IL_0006:  ret
+  } 
+
   .method assembly static int32  CompareTo$cont@4(class assembly/Test1 this,
                                                   class assembly/Test1 obj,
                                                   class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed
@@ -1389,42 +1415,6 @@
     IL_00fc:  ret
   } 
 
-  .method public static int32  select1(class assembly/Test1 x) cil managed
-  {
-    
-    .maxstack  8
-    IL_0000:  nop
-    IL_0001:  ldarg.0
-    IL_0002:  call       instance int32 assembly/Test1::get_Tag()
-    IL_0007:  switch     ( 
-                          IL_001c,
-                          IL_0028,
-                          IL_002a,
-                          IL_002c)
-    IL_001c:  ldarg.0
-    IL_001d:  castclass  assembly/Test1/X11
-    IL_0022:  ldfld      int32 assembly/Test1/X11::item
-    IL_0027:  ret
-
-    IL_0028:  ldc.i4.2
-    IL_0029:  ret
-
-    IL_002a:  ldc.i4.3
-    IL_002b:  ret
-
-    IL_002c:  ldc.i4.4
-    IL_002d:  ret
-  } 
-
-  .method public static int32  fm(class assembly/Test1 y) cil managed
-  {
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       int32 assembly::select1(class assembly/Test1)
-    IL_0006:  ret
-  } 
-
 } 
 
 .class private abstract auto ansi sealed ''.$assembly
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/AnonRecd.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/AnonRecd.fs.il.net472.bsl
index 51ecb51bb67..bcf7c7ea3c9 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/AnonRecd.fs.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/AnonRecd.fs.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/EqualsOnUnions01.fs.il.net472.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/EqualsOnUnions01.fs.il.net472.release.bsl
index 59329f4b4ac..3b253236dad 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/EqualsOnUnions01.fs.il.net472.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/EqualsOnUnions01.fs.il.net472.release.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/GeneralizationOnUnions01.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/GeneralizationOnUnions01.fs.il.net472.bsl
index f0bf8062180..1b742f503b0 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/GeneralizationOnUnions01.fs.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/GeneralizationOnUnions01.fs.il.net472.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.net472.bsl
index 66aa48e83f6..46a2abb57c3 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/AnonRecords.fs.il.net472.bsl
@@ -708,6 +708,7 @@
 .class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field private valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType@
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
@@ -820,6 +821,7 @@
 .class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field public uint8 Flag
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.net472.bsl
new file mode 100644
index 00000000000..083abfd072c
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.net472.bsl
@@ -0,0 +1,205 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .class auto ansi serializable sealed nested assembly beforefieldinit partiallyAplied@8
+         extends class [FSharp.Core]Microsoft.FSharp.Core.OptimizedClosures/FSharpFunc`3>
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .field public string propperString
+    .method assembly specialname rtspecialname 
+            instance void  .ctor(string propperString) cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void class [FSharp.Core]Microsoft.FSharp.Core.OptimizedClosures/FSharpFunc`3>::.ctor()
+      IL_0006:  ldarg.0
+      IL_0007:  ldarg.1
+      IL_0008:  stfld      string MyTestModule/partiallyAplied@8::propperString
+      IL_000d:  ret
+    } 
+
+    .method public strict virtual instance class [runtime]System.Tuple`3 
+            Invoke(string b,
+                   int32 c) cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string MyTestModule/partiallyAplied@8::propperString
+      IL_0006:  ldarg.1
+      IL_0007:  ldarg.2
+      IL_0008:  newobj     instance void class [runtime]System.Tuple`3::.ctor(!0,
+                                                                                                    !1,
+                                                                                                    !2)
+      IL_000d:  ret
+    } 
+
+  } 
+
+  .method public static class [runtime]System.Tuple`3 
+          curried3Func(string a,
+                       string b,
+                       int32 c) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 
+                                                                                                                    00 00 00 00 ) 
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 01 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldarg.1
+    IL_0002:  ldarg.2
+    IL_0003:  newobj     instance void class [runtime]System.Tuple`3::.ctor(!0,
+                                                                                                  !1,
+                                                                                                  !2)
+    IL_0008:  ret
+  } 
+
+  .method public static class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>> 
+          partiallyAplied(string propperString) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 06 00 00 00 01 01 01 01 02 01 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  newobj     instance void MyTestModule/partiallyAplied@8::.ctor(string)
+    IL_0006:  ret
+  } 
+
+  .method public static !!b  secondOutOfTriple(!!a a,
+                                                          !!b b,
+                                                          !!c c,
+                                                          !!d d,
+                                                          !!e e) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 03 00 00 00 01 00 00 00 01 00 
+                                                                                                                    00 00 00 00 ) 
+    .param type a 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    .param type b 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type c 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    .param type d 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    .param type e 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.1
+    IL_0001:  ret
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.netcore.bsl
similarity index 100%
rename from tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.bsl
rename to tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CurriedFunctions.fs.il.netcore.bsl
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.net472.bsl
new file mode 100644
index 00000000000..e7727e1c38b
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.net472.bsl
@@ -0,0 +1,353 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .class auto ansi serializable nested public Myassembly
+         extends [runtime]System.Object
+  {
+    .custom instance void [runtime]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 )                      
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .field static assembly string uglyGlobalMutableString
+    .field static assembly string uglyGlobalMutableNullableString
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .field static assembly class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 dict
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 02 00 00 ) 
+    .field assembly string Nullable@
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .field assembly string NonNullable@
+    .field assembly int32 JustSomeInt@
+    .field static assembly int32 init@6
+    .method public specialname rtspecialname 
+            instance void  .ctor(string x,
+                                 string y) cil managed
+    {
+      .param [1]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  callvirt   instance void [runtime]System.Object::.ctor()
+      IL_0006:  ldarg.0
+      IL_0007:  pop
+      IL_0008:  ldarg.0
+      IL_0009:  ldarg.1
+      IL_000a:  stfld      string MyTestModule/Myassembly::Nullable@
+      IL_000f:  ldarg.0
+      IL_0010:  ldarg.2
+      IL_0011:  stfld      string MyTestModule/Myassembly::NonNullable@
+      IL_0016:  ldarg.0
+      IL_0017:  ldc.i4.s   42
+      IL_0019:  stfld      int32 MyTestModule/Myassembly::JustSomeInt@
+      IL_001e:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance string  get_Nullable() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string MyTestModule/Myassembly::Nullable@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance string  get_NonNullable() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string MyTestModule/Myassembly::NonNullable@
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance int32  get_JustSomeInt() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      int32 MyTestModule/Myassembly::JustSomeInt@
+      IL_0006:  ret
+    } 
+
+    .method public static string  GiveMeNull() cil managed
+    {
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldnull
+      IL_0001:  ret
+    } 
+
+    .method public static string  GiveMeString() cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  ldstr      ""
+      IL_0005:  ret
+    } 
+
+    .method public hidebysig instance void 
+            UnitFunc() cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  ret
+    } 
+
+    .method public hidebysig instance class MyTestModule/Myassembly 
+            GetThis() cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ret
+    } 
+
+    .method public hidebysig instance class MyTestModule/Myassembly 
+            GetThisOrNull() cil managed
+    {
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldnull
+      IL_0001:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance string  get_Item(string index) cil managed
+    {
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .param [1]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  volatile.
+      IL_0002:  ldsfld     int32 MyTestModule/Myassembly::init@6
+      IL_0007:  ldc.i4.4
+      IL_0008:  bge.s      IL_0011
+
+      IL_000a:  call       void [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::FailStaticInit()
+      IL_000f:  br.s       IL_0011
+
+      IL_0011:  ldsfld     class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 MyTestModule/Myassembly::dict
+      IL_0016:  ldarg.1
+      IL_0017:  tail.
+      IL_0019:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2::get_Item(!0)
+      IL_001e:  ret
+    } 
+
+    .method public hidebysig specialname 
+            instance void  set_Item(string index,
+                                    string 'value') cil managed
+    {
+      .param [1]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .param [2]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  volatile.
+      IL_0002:  ldsfld     int32 MyTestModule/Myassembly::init@6
+      IL_0007:  ldc.i4.4
+      IL_0008:  bge.s      IL_0011
+
+      IL_000a:  call       void [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::FailStaticInit()
+      IL_000f:  br.s       IL_0011
+
+      IL_0011:  volatile.
+      IL_0013:  ldsfld     int32 MyTestModule/Myassembly::init@6
+      IL_0018:  ldc.i4.4
+      IL_0019:  bge.s      IL_0022
+
+      IL_001b:  call       void [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::FailStaticInit()
+      IL_0020:  br.s       IL_0022
+
+      IL_0022:  ldsfld     class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 MyTestModule/Myassembly::dict
+      IL_0027:  ldarg.1
+      IL_0028:  ldarg.2
+      IL_0029:  callvirt   instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2::Add(!0,
+                                                                                                                                                                                       !1)
+      IL_002e:  stsfld     class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 MyTestModule/Myassembly::dict
+      IL_0033:  ret
+    } 
+
+    .method private specialname rtspecialname static 
+            void  .cctor() cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  ldc.i4.0
+      IL_0001:  stsfld     int32 ''.$MyTestModule::init@
+      IL_0006:  ldsfld     int32 ''.$MyTestModule::init@
+      IL_000b:  pop
+      IL_000c:  ret
+    } 
+
+    .property instance string Nullable()
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .get instance string MyTestModule/Myassembly::get_Nullable()
+    } 
+    .property instance string NonNullable()
+    {
+      .get instance string MyTestModule/Myassembly::get_NonNullable()
+    } 
+    .property instance int32 JustSomeInt()
+    {
+      .get instance int32 MyTestModule/Myassembly::get_JustSomeInt()
+    } 
+    .property instance string Item(string)
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .set instance void MyTestModule/Myassembly::set_Item(string,
+                                                             string)
+      .get instance string MyTestModule/Myassembly::get_Item(string)
+    } 
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .field static assembly int32 init@
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method private specialname rtspecialname static 
+          void  .cctor() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldstr      ""
+    IL_0005:  stsfld     string MyTestModule/Myassembly::uglyGlobalMutableString
+    IL_000a:  ldc.i4.2
+    IL_000b:  volatile.
+    IL_000d:  stsfld     int32 MyTestModule/Myassembly::init@6
+    IL_0012:  ldnull
+    IL_0013:  stsfld     string MyTestModule/Myassembly::uglyGlobalMutableNullableString
+    IL_0018:  ldc.i4.3
+    IL_0019:  volatile.
+    IL_001b:  stsfld     int32 MyTestModule/Myassembly::init@6
+    IL_0020:  call       class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 [FSharp.Core]Microsoft.FSharp.Collections.MapModule::Empty()
+    IL_0025:  stsfld     class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 MyTestModule/Myassembly::dict
+    IL_002a:  ldc.i4.4
+    IL_002b:  volatile.
+    IL_002d:  stsfld     int32 MyTestModule/Myassembly::init@6
+    IL_0032:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.netcore.bsl
similarity index 100%
rename from tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.bsl
rename to tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/CustomType.fs.il.netcore.bsl
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.net472.bsl
new file mode 100644
index 00000000000..b2e69c91ff5
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.net472.bsl
@@ -0,0 +1,232 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .field public static literal string nullableLiteral = ""
+  .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.LiteralAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .method public specialname static string 
+          get_notNullStringField() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldstr      ""
+    IL_0005:  ret
+  } 
+
+  .method public specialname static string 
+          get_nullableStringField() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldnull
+    IL_0001:  ret
+  } 
+
+  .method public specialname static string 
+          get_nullableMutableStringField() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldsfld     string ''.$MyTestModule::nullableMutableStringField@6
+    IL_0005:  ret
+  } 
+
+  .method public specialname static void 
+          set_nullableMutableStringField(string 'value') cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  stsfld     string ''.$MyTestModule::nullableMutableStringField@6
+    IL_0006:  ret
+  } 
+
+  .method public specialname static valuetype [runtime]System.Nullable`1 
+          get_nullableInt() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  3
+    .locals init (valuetype [runtime]System.Nullable`1 V_0)
+    IL_0000:  ldloc.0
+    IL_0001:  ret
+  } 
+
+  .method public specialname static int32 
+          get_regularInt() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldc.i4.s   42
+    IL_0002:  ret
+  } 
+
+  .method private specialname rtspecialname static 
+          void  .cctor() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldc.i4.0
+    IL_0001:  stsfld     int32 ''.$MyTestModule::init@
+    IL_0006:  ldsfld     int32 ''.$MyTestModule::init@
+    IL_000b:  pop
+    IL_000c:  ret
+  } 
+
+  .property string notNullStringField()
+  {
+    .get string MyTestModule::get_notNullStringField()
+  } 
+  .property string nullableStringField()
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .get string MyTestModule::get_nullableStringField()
+  } 
+  .property string nullableMutableStringField()
+  {
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) 
+    .set void MyTestModule::set_nullableMutableStringField(string)
+    .get string MyTestModule::get_nullableMutableStringField()
+  } 
+  .property valuetype [runtime]System.Nullable`1
+          nullableInt()
+  {
+    .get valuetype [runtime]System.Nullable`1 MyTestModule::get_nullableInt()
+  } 
+  .property int32 regularInt()
+  {
+    .get int32 MyTestModule::get_regularInt()
+  } 
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .field static assembly string nullableMutableStringField@6
+  .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .field static assembly int32 init@
+  .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method private specialname rtspecialname static 
+          void  .cctor() cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldnull
+    IL_0001:  stsfld     string ''.$MyTestModule::nullableMutableStringField@6
+    IL_0006:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.netcore.bsl
similarity index 100%
rename from tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.bsl
rename to tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelBindings.fs.il.netcore.bsl
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.net472.bsl
new file mode 100644
index 00000000000..0461633d8bd
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.net472.bsl
@@ -0,0 +1,216 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .method public static string  nonNullableInputOutputFunc(string x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static string  nullableStringInputOutputFunc(string x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static int32  nonNullableIntFunc(int32 x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static valuetype [runtime]System.Nullable`1 
+          nullableIntFunc(valuetype [runtime]System.Nullable`1 x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static valuetype [runtime]System.ValueTuple`6 
+          genericValueTypeTest(valuetype [runtime]System.ValueTuple`6 x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static class [runtime]System.Tuple`6 
+          genericRefTypeTest(string x_0,
+                             string x_1,
+                             int32 x_2,
+                             int32 x_3,
+                             int32 x_4,
+                             int32 x_5) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
+    .param [2]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    .locals init (class [runtime]System.Tuple`6 V_0)
+    IL_0000:  ldarg.0
+    IL_0001:  ldarg.1
+    IL_0002:  ldarg.2
+    IL_0003:  ldarg.3
+    IL_0004:  ldarg.s    x_4
+    IL_0006:  ldarg.s    x_5
+    IL_0008:  newobj     instance void class [runtime]System.Tuple`6::.ctor(!0,
+                                                                                                                    !1,
+                                                                                                                    !2,
+                                                                                                                    !3,
+                                                                                                                    !4,
+                                                                                                                    !5)
+    IL_000d:  stloc.0
+    IL_000e:  ldloc.0
+    IL_000f:  ret
+  } 
+
+  .method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> 
+          nestedGenericsTest(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static int32  multiArgumentTest(string x,
+                                                 string y) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+    .param [2]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldc.i4.s   42
+    IL_0002:  ret
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.netcore.bsl
similarity index 100%
rename from tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.bsl
rename to tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctions.fs.il.netcore.bsl
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.net472.bsl
new file mode 100644
index 00000000000..f4d927102b4
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.net472.bsl
@@ -0,0 +1,213 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed MyTestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .method public static string  nonNullableInputOutputFunc(string x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static string  nullableStringInputOutputFunc(string x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static int32  nonNullableIntFunc(int32 x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static valuetype [runtime]System.Nullable`1 
+          nullableIntFunc(valuetype [runtime]System.Nullable`1 x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static valuetype [runtime]System.ValueTuple`6 
+          genericValueTypeTest(valuetype [runtime]System.ValueTuple`6 x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static class [runtime]System.Tuple`6 
+          genericRefTypeTest(string x_0,
+                             string x_1,
+                             int32 x_2,
+                             int32 x_3,
+                             int32 x_4,
+                             int32 x_5) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
+    .param [2]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldarg.1
+    IL_0002:  ldarg.2
+    IL_0003:  ldarg.3
+    IL_0004:  ldarg.s    x_4
+    IL_0006:  ldarg.s    x_5
+    IL_0008:  newobj     instance void class [runtime]System.Tuple`6::.ctor(!0,
+                                                                                                                    !1,
+                                                                                                                    !2,
+                                                                                                                    !3,
+                                                                                                                    !4,
+                                                                                                                    !5)
+    IL_000d:  ret
+  } 
+
+  .method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> 
+          nestedGenericsTest(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> x) cil managed
+  {
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    .param [1]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } 
+
+  .method public static int32  multiArgumentTest(string x,
+                                                 string y) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+    .param [2]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldc.i4.s   42
+    IL_0002:  ret
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$MyTestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.netcore.bsl
similarity index 100%
rename from tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.bsl
rename to tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ModuleLevelFunctionsOpt.fs.il.netcore.bsl
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl
index b87de0f1315..f2a1074fb26 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl
@@ -836,6 +836,7 @@
 .class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field private valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType@
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
@@ -904,6 +905,7 @@
 .class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field private bool ReturnValue@
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
@@ -1014,6 +1016,7 @@
 .class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field public uint8 Flag
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.net472.bsl
index 709a072afd7..01a99cf449b 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/Records.fs.il.net472.bsl
@@ -322,6 +322,7 @@
 .class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field private valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType@
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
@@ -434,6 +435,7 @@
 .class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field public uint8 Flag
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.net472.bsl
index 8766a7a551b..c037f110df1 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/ReferenceDU.fs.il.net472.bsl
@@ -634,6 +634,7 @@
 .class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field private valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType@
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
@@ -746,6 +747,7 @@
 .class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field public uint8 Flag
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.net472.bsl
index 22600dd10f1..83c9e539fa5 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/StructDU.fs.il.net472.bsl
@@ -370,6 +370,7 @@
 .class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field private valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType@
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
@@ -438,6 +439,7 @@
 .class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field private bool ReturnValue@
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
@@ -548,6 +550,7 @@
 .class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
        extends [runtime]System.Attribute
 {
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .field public uint8 Flag
   .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
   .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelModule.fs.il.net472.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelModule.fs.il.net472.release.bsl
index 278f568a6bc..20700664ae4 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelModule.fs.il.net472.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelModule.fs.il.net472.release.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelModule60.fs.il.net472.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelModule60.fs.il.net472.release.bsl
index 8b78edc5598..2ee33c38d65 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelModule60.fs.il.net472.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelModule60.fs.il.net472.release.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelNamespace.fs.il.net472.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelNamespace.fs.il.net472.release.bsl
index 2be8144663d..7e898a1bca6 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelNamespace.fs.il.net472.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelNamespace.fs.il.net472.release.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelNamespace60.fs.il.net472.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelNamespace60.fs.il.net472.release.bsl
index b3623429e88..43305b35b36 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelNamespace60.fs.il.net472.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SerializableAttribute/ToplevelNamespace60.fs.il.net472.release.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SteppingMatch/SteppingMatch06.fs.il.net472.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SteppingMatch/SteppingMatch06.fs.il.net472.release.bsl
index fb7c3431ced..7f6eb55a990 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SteppingMatch/SteppingMatch06.fs.il.net472.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SteppingMatch/SteppingMatch06.fs.il.net472.release.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SteppingMatch/SteppingMatch07.fs.il.net472.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SteppingMatch/SteppingMatch07.fs.il.net472.release.bsl
index 4b144f52257..020b2596f01 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/SteppingMatch/SteppingMatch07.fs.il.net472.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/SteppingMatch/SteppingMatch07.fs.il.net472.release.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction16.fs.il.net472.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction16.fs.il.net472.release.bsl
index 72cd3147c78..1645b13c229 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction16.fs.il.net472.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction16.fs.il.net472.release.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction17.fs.il.net472.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction17.fs.il.net472.release.bsl
index fe647c1c17b..db670773e29 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction17.fs.il.net472.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction17.fs.il.net472.release.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction21.fs.il.net472.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction21.fs.il.net472.release.bsl
index a47ad1aa6d4..aff294c8ffd 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction21.fs.il.net472.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction21.fs.il.net472.release.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction24.fs.il.net472.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction24.fs.il.net472.release.bsl
index 91bf013b138..8cd339e845b 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction24.fs.il.net472.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction24.fs.il.net472.release.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/Verify13043.fs.il.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/Verify13043.fs.il.release.bsl
index db118790e53..b41b703c2cb 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/Verify13043.fs.il.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/Verify13043.fs.il.release.bsl
@@ -16,16 +16,6 @@
 
   .hash algorithm 0x00008004
   .ver 0:0:0:0
-}
-.mresource public FSharpSignatureData.assembly
-{
-  
-  
-}
-.mresource public FSharpOptimizationData.assembly
-{
-  
-  
 }
 .module assembly.exe
 
@@ -43,6 +33,82 @@
        extends [runtime]System.Object
 {
   .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .class auto ansi serializable sealed nested assembly beforefieldinit matchResult@38
+         extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2
+  {
+    .field static assembly initonly class assembly/matchResult@38 @_instance
+    .method assembly specialname rtspecialname 
+            instance void  .ctor() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor()
+      IL_0006:  ret
+    } 
+
+    .method public strict virtual instance bool 
+            Invoke(int32 n) cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  ldarg.1
+      IL_0001:  call       bool assembly::condition(int32)
+      IL_0006:  ret
+    } 
+
+    .method private specialname rtspecialname static 
+            void  .cctor() cil managed
+    {
+      
+      .maxstack  10
+      IL_0000:  newobj     instance void assembly/matchResult@38::.ctor()
+      IL_0005:  stsfld     class assembly/matchResult@38 assembly/matchResult@38::@_instance
+      IL_000a:  ret
+    } 
+
+  } 
+
+  .class auto ansi serializable sealed nested assembly beforefieldinit functionResult@43
+         extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2
+  {
+    .field static assembly initonly class assembly/functionResult@43 @_instance
+    .method assembly specialname rtspecialname 
+            instance void  .ctor() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor()
+      IL_0006:  ret
+    } 
+
+    .method public strict virtual instance bool 
+            Invoke(int32 n) cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  ldarg.1
+      IL_0001:  call       bool assembly::condition(int32)
+      IL_0006:  ret
+    } 
+
+    .method private specialname rtspecialname static 
+            void  .cctor() cil managed
+    {
+      
+      .maxstack  10
+      IL_0000:  newobj     instance void assembly/functionResult@43::.ctor()
+      IL_0005:  stsfld     class assembly/functionResult@43 assembly/functionResult@43::@_instance
+      IL_000a:  ret
+    } 
+
+  } 
+
   .class auto ansi serializable sealed nested assembly beforefieldinit f@8
          extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>
   {
@@ -177,82 +243,6 @@
 
   } 
 
-  .class auto ansi serializable sealed nested assembly beforefieldinit matchResult@38
-         extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2
-  {
-    .field static assembly initonly class assembly/matchResult@38 @_instance
-    .method assembly specialname rtspecialname 
-            instance void  .ctor() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  call       instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor()
-      IL_0006:  ret
-    } 
-
-    .method public strict virtual instance bool 
-            Invoke(int32 n) cil managed
-    {
-      
-      .maxstack  8
-      IL_0000:  ldarg.1
-      IL_0001:  call       bool assembly::condition(int32)
-      IL_0006:  ret
-    } 
-
-    .method private specialname rtspecialname static 
-            void  .cctor() cil managed
-    {
-      
-      .maxstack  10
-      IL_0000:  newobj     instance void assembly/matchResult@38::.ctor()
-      IL_0005:  stsfld     class assembly/matchResult@38 assembly/matchResult@38::@_instance
-      IL_000a:  ret
-    } 
-
-  } 
-
-  .class auto ansi serializable sealed nested assembly beforefieldinit functionResult@43
-         extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2
-  {
-    .field static assembly initonly class assembly/functionResult@43 @_instance
-    .method assembly specialname rtspecialname 
-            instance void  .ctor() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  call       instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor()
-      IL_0006:  ret
-    } 
-
-    .method public strict virtual instance bool 
-            Invoke(int32 n) cil managed
-    {
-      
-      .maxstack  8
-      IL_0000:  ldarg.1
-      IL_0001:  call       bool assembly::condition(int32)
-      IL_0006:  ret
-    } 
-
-    .method private specialname rtspecialname static 
-            void  .cctor() cil managed
-    {
-      
-      .maxstack  10
-      IL_0000:  newobj     instance void assembly/functionResult@43::.ctor()
-      IL_0005:  stsfld     class assembly/functionResult@43 assembly/functionResult@43::@_instance
-      IL_000a:  ret
-    } 
-
-  } 
-
   .method public specialname static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 
           get_list() cil managed
   {

From 97a9c3142fab9b2de3895bd420c6d7340c2bac46 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Fri, 1 Dec 2023 11:36:47 +0100
Subject: [PATCH 41/59] trim test

---
 tests/AheadOfTime/Trimming/check.ps1 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index 62856de6383..85f7060a852 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -38,7 +38,7 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) {
 # NOTE: Trimming now errors out on desktop TFMs, as shown below:
 # error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher.
 
-$expectedForSelfContained = (If ($compressAllMetadata) {300032} Else {288256 })
+$expectedForSelfContained = If ($compressAllMetadata) {300032} Else {288256}
 
 # Check net7.0 trimmed assemblies
 CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len $expectedForSelfContained

From 51044a7d1cfaf19fd6934a849e16b81113d99d6c Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Fri, 1 Dec 2023 11:42:32 +0100
Subject: [PATCH 42/59] trimming test

---
 tests/AheadOfTime/Trimming/check.ps1 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index 85f7060a852..1af64ad8a1a 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -38,7 +38,7 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) {
 # NOTE: Trimming now errors out on desktop TFMs, as shown below:
 # error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher.
 
-$expectedForSelfContained = If ($compressAllMetadata) {300032} Else {288256}
+$expectedForSelfContained = if ($compressAllMetadata) {300032} else {288256}
 
 # Check net7.0 trimmed assemblies
 CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len $expectedForSelfContained

From 71829138c6937793a790bd530576123369da6477 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Fri, 1 Dec 2023 13:09:30 +0100
Subject: [PATCH 43/59] trim check

---
 tests/AheadOfTime/Trimming/check.ps1 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index 1af64ad8a1a..ea4b7716b4c 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -38,7 +38,7 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) {
 # NOTE: Trimming now errors out on desktop TFMs, as shown below:
 # error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher.
 
-$expectedForSelfContained = if ($compressAllMetadata) {300032} else {288256}
+$expectedForSelfContained = if ($compressAllMetadata) {300032} else {300032}
 
 # Check net7.0 trimmed assemblies
 CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len $expectedForSelfContained

From 26de6fe01e6e40a86c8156833559e01bc5e1cc67 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Fri, 1 Dec 2023 13:38:01 +0100
Subject: [PATCH 44/59] now?

---
 tests/AheadOfTime/Trimming/check.ps1 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index ea4b7716b4c..59bb0713dc4 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -38,7 +38,7 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) {
 # NOTE: Trimming now errors out on desktop TFMs, as shown below:
 # error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher.
 
-$expectedForSelfContained = if ($compressAllMetadata) {300032} else {300032}
+$expectedForSelfContained = if ($compressAllMetadata) {288256} else {300032}
 
 # Check net7.0 trimmed assemblies
 CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len $expectedForSelfContained

From 8f48a32ec6fd25f31a8b451a6884c2fba99bdc16 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Mon, 4 Dec 2023 12:31:55 +0100
Subject: [PATCH 45/59] IL tests

---
 .../Inlining/Match01.fs.il.net472.release.bsl |  72 ++++-----
 .../Verify13043.fs.il.release.bsl             | 152 +++++++++---------
 2 files changed, 112 insertions(+), 112 deletions(-)

diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.net472.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.net472.release.bsl
index 6848ff990e2..68696b1f7f6 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.net472.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.net472.release.bsl
@@ -1110,42 +1110,6 @@
     } 
   } 
 
-  .method public static int32  select1(class assembly/Test1 x) cil managed
-  {
-    
-    .maxstack  8
-    IL_0000:  nop
-    IL_0001:  ldarg.0
-    IL_0002:  call       instance int32 assembly/Test1::get_Tag()
-    IL_0007:  switch     ( 
-                          IL_001c,
-                          IL_0028,
-                          IL_002a,
-                          IL_002c)
-    IL_001c:  ldarg.0
-    IL_001d:  castclass  assembly/Test1/X11
-    IL_0022:  ldfld      int32 assembly/Test1/X11::item
-    IL_0027:  ret
-
-    IL_0028:  ldc.i4.2
-    IL_0029:  ret
-
-    IL_002a:  ldc.i4.3
-    IL_002b:  ret
-
-    IL_002c:  ldc.i4.4
-    IL_002d:  ret
-  } 
-
-  .method public static int32  fm(class assembly/Test1 y) cil managed
-  {
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       int32 assembly::select1(class assembly/Test1)
-    IL_0006:  ret
-  } 
-
   .method assembly static int32  CompareTo$cont@4(class assembly/Test1 this,
                                                   class assembly/Test1 obj,
                                                   class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed
@@ -1415,6 +1379,42 @@
     IL_00fc:  ret
   } 
 
+  .method public static int32  select1(class assembly/Test1 x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  nop
+    IL_0001:  ldarg.0
+    IL_0002:  call       instance int32 assembly/Test1::get_Tag()
+    IL_0007:  switch     ( 
+                          IL_001c,
+                          IL_0028,
+                          IL_002a,
+                          IL_002c)
+    IL_001c:  ldarg.0
+    IL_001d:  castclass  assembly/Test1/X11
+    IL_0022:  ldfld      int32 assembly/Test1/X11::item
+    IL_0027:  ret
+
+    IL_0028:  ldc.i4.2
+    IL_0029:  ret
+
+    IL_002a:  ldc.i4.3
+    IL_002b:  ret
+
+    IL_002c:  ldc.i4.4
+    IL_002d:  ret
+  } 
+
+  .method public static int32  fm(class assembly/Test1 y) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       int32 assembly::select1(class assembly/Test1)
+    IL_0006:  ret
+  } 
+
 } 
 
 .class private abstract auto ansi sealed ''.$assembly
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/Verify13043.fs.il.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/Verify13043.fs.il.release.bsl
index b41b703c2cb..480e534015f 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/Verify13043.fs.il.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/Verify13043.fs.il.release.bsl
@@ -33,82 +33,6 @@
        extends [runtime]System.Object
 {
   .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
-  .class auto ansi serializable sealed nested assembly beforefieldinit matchResult@38
-         extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2
-  {
-    .field static assembly initonly class assembly/matchResult@38 @_instance
-    .method assembly specialname rtspecialname 
-            instance void  .ctor() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  call       instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor()
-      IL_0006:  ret
-    } 
-
-    .method public strict virtual instance bool 
-            Invoke(int32 n) cil managed
-    {
-      
-      .maxstack  8
-      IL_0000:  ldarg.1
-      IL_0001:  call       bool assembly::condition(int32)
-      IL_0006:  ret
-    } 
-
-    .method private specialname rtspecialname static 
-            void  .cctor() cil managed
-    {
-      
-      .maxstack  10
-      IL_0000:  newobj     instance void assembly/matchResult@38::.ctor()
-      IL_0005:  stsfld     class assembly/matchResult@38 assembly/matchResult@38::@_instance
-      IL_000a:  ret
-    } 
-
-  } 
-
-  .class auto ansi serializable sealed nested assembly beforefieldinit functionResult@43
-         extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2
-  {
-    .field static assembly initonly class assembly/functionResult@43 @_instance
-    .method assembly specialname rtspecialname 
-            instance void  .ctor() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  call       instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor()
-      IL_0006:  ret
-    } 
-
-    .method public strict virtual instance bool 
-            Invoke(int32 n) cil managed
-    {
-      
-      .maxstack  8
-      IL_0000:  ldarg.1
-      IL_0001:  call       bool assembly::condition(int32)
-      IL_0006:  ret
-    } 
-
-    .method private specialname rtspecialname static 
-            void  .cctor() cil managed
-    {
-      
-      .maxstack  10
-      IL_0000:  newobj     instance void assembly/functionResult@43::.ctor()
-      IL_0005:  stsfld     class assembly/functionResult@43 assembly/functionResult@43::@_instance
-      IL_000a:  ret
-    } 
-
-  } 
-
   .class auto ansi serializable sealed nested assembly beforefieldinit f@8
          extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>
   {
@@ -243,6 +167,82 @@
 
   } 
 
+  .class auto ansi serializable sealed nested assembly beforefieldinit matchResult@38
+         extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2
+  {
+    .field static assembly initonly class assembly/matchResult@38 @_instance
+    .method assembly specialname rtspecialname 
+            instance void  .ctor() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor()
+      IL_0006:  ret
+    } 
+
+    .method public strict virtual instance bool 
+            Invoke(int32 n) cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  ldarg.1
+      IL_0001:  call       bool assembly::condition(int32)
+      IL_0006:  ret
+    } 
+
+    .method private specialname rtspecialname static 
+            void  .cctor() cil managed
+    {
+      
+      .maxstack  10
+      IL_0000:  newobj     instance void assembly/matchResult@38::.ctor()
+      IL_0005:  stsfld     class assembly/matchResult@38 assembly/matchResult@38::@_instance
+      IL_000a:  ret
+    } 
+
+  } 
+
+  .class auto ansi serializable sealed nested assembly beforefieldinit functionResult@43
+         extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2
+  {
+    .field static assembly initonly class assembly/functionResult@43 @_instance
+    .method assembly specialname rtspecialname 
+            instance void  .ctor() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor()
+      IL_0006:  ret
+    } 
+
+    .method public strict virtual instance bool 
+            Invoke(int32 n) cil managed
+    {
+      
+      .maxstack  8
+      IL_0000:  ldarg.1
+      IL_0001:  call       bool assembly::condition(int32)
+      IL_0006:  ret
+    } 
+
+    .method private specialname rtspecialname static 
+            void  .cctor() cil managed
+    {
+      
+      .maxstack  10
+      IL_0000:  newobj     instance void assembly/functionResult@43::.ctor()
+      IL_0005:  stsfld     class assembly/functionResult@43 assembly/functionResult@43::@_instance
+      IL_000a:  ret
+    } 
+
+  } 
+
   .method public specialname static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 
           get_list() cil managed
   {

From 3f763a57ffc6026723f15409f3b6cb206ea87c4e Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Mon, 4 Dec 2023 12:32:52 +0100
Subject: [PATCH 46/59] il tests

---
 .../Match01.fs.il.netcore.release.bsl         | 72 +++++++++----------
 1 file changed, 36 insertions(+), 36 deletions(-)

diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.netcore.release.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.netcore.release.bsl
index 9cfa59775d0..0429f8c1d99 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.netcore.release.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Match01.fs.il.netcore.release.bsl
@@ -1110,42 +1110,6 @@
     } 
   } 
 
-  .method public static int32  select1(class assembly/Test1 x) cil managed
-  {
-    
-    .maxstack  8
-    IL_0000:  nop
-    IL_0001:  ldarg.0
-    IL_0002:  call       instance int32 assembly/Test1::get_Tag()
-    IL_0007:  switch     ( 
-                          IL_001c,
-                          IL_0028,
-                          IL_002a,
-                          IL_002c)
-    IL_001c:  ldarg.0
-    IL_001d:  castclass  assembly/Test1/X11
-    IL_0022:  ldfld      int32 assembly/Test1/X11::item
-    IL_0027:  ret
-
-    IL_0028:  ldc.i4.2
-    IL_0029:  ret
-
-    IL_002a:  ldc.i4.3
-    IL_002b:  ret
-
-    IL_002c:  ldc.i4.4
-    IL_002d:  ret
-  } 
-
-  .method public static int32  fm(class assembly/Test1 y) cil managed
-  {
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       int32 assembly::select1(class assembly/Test1)
-    IL_0006:  ret
-  } 
-
   .method assembly static int32  CompareTo$cont@4(class assembly/Test1 this,
                                                   class assembly/Test1 obj,
                                                   class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed
@@ -1415,6 +1379,42 @@
     IL_00fc:  ret
   } 
 
+  .method public static int32  select1(class assembly/Test1 x) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  nop
+    IL_0001:  ldarg.0
+    IL_0002:  call       instance int32 assembly/Test1::get_Tag()
+    IL_0007:  switch     ( 
+                          IL_001c,
+                          IL_0028,
+                          IL_002a,
+                          IL_002c)
+    IL_001c:  ldarg.0
+    IL_001d:  castclass  assembly/Test1/X11
+    IL_0022:  ldfld      int32 assembly/Test1/X11::item
+    IL_0027:  ret
+
+    IL_0028:  ldc.i4.2
+    IL_0029:  ret
+
+    IL_002a:  ldc.i4.3
+    IL_002b:  ret
+
+    IL_002c:  ldc.i4.4
+    IL_002d:  ret
+  } 
+
+  .method public static int32  fm(class assembly/Test1 y) cil managed
+  {
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       int32 assembly::select1(class assembly/Test1)
+    IL_0006:  ret
+  } 
+
 } 
 
 .class private abstract auto ansi sealed ''.$assembly

From cbfe7776ef09ae6c487a589877105389a66b9667 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Mon, 4 Dec 2023 13:56:55 +0100
Subject: [PATCH 47/59] trim test

---
 tests/AheadOfTime/Trimming/check.ps1 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index 59bb0713dc4..fb7c57de6a3 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -38,7 +38,7 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) {
 # NOTE: Trimming now errors out on desktop TFMs, as shown below:
 # error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher.
 
-$expectedForSelfContained = if ($compressAllMetadata) {288256} else {300032}
+$expectedForSelfContained = if ($compressAllMetadata) {288256} else {288256}
 
 # Check net7.0 trimmed assemblies
 CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len $expectedForSelfContained

From 5e296b96100a21783c5d78d29307c733c77c058c Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Mon, 4 Dec 2023 14:45:32 +0100
Subject: [PATCH 48/59] trim

---
 tests/AheadOfTime/Trimming/check.ps1 | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index fb7c57de6a3..7c27ec37172 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -1,5 +1,7 @@
 function CheckTrim($root, $tfm, $outputfile, $expected_len) {
     Write-Host "Publish and Execute: ${tfm} - ${root}"
+    Write-Host "Expecting ${expected_len}"
+    Write-Host "CompressAllMetadata value: ${compressAllMetadata}"
 
     $cwd = Get-Location
     Set-Location (Join-Path $PSScriptRoot "${root}")
@@ -38,7 +40,7 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) {
 # NOTE: Trimming now errors out on desktop TFMs, as shown below:
 # error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher.
 
-$expectedForSelfContained = if ($compressAllMetadata) {288256} else {288256}
+$expectedForSelfContained = if ($compressAllMetadata) {300032} else {288256}
 
 # Check net7.0 trimmed assemblies
 CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len $expectedForSelfContained

From dec61d614633472b4e104504b0d3835f42d993a2 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Mon, 4 Dec 2023 15:28:28 +0100
Subject: [PATCH 49/59] one more time

---
 tests/AheadOfTime/Trimming/check.ps1 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index 7c27ec37172..add84fdd2df 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -39,7 +39,7 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) {
 
 # NOTE: Trimming now errors out on desktop TFMs, as shown below:
 # error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher.
-
+$compressAllMetadata = $env:_kind -eq "-compressAllMetadata"
 $expectedForSelfContained = if ($compressAllMetadata) {300032} else {288256}
 
 # Check net7.0 trimmed assemblies

From 91429b4c62b6bfc46c98c98091d5d95f3d2799a0 Mon Sep 17 00:00:00 2001
From: dotnet bot 
Date: Mon, 4 Dec 2023 06:50:47 -0800
Subject: [PATCH 50/59] Merge main to feature/nullness (#16366)

* Fixes #16359 - correctly handle imports with 0 length public key tokens (#16363)

* Parser: recover on unfinished record decls, fix field ranges (#16357)

* Parser: recover on unfinished record decls, fix field ranges

* Fantomas

* Better diagnostic ranges for fields

* More parser tests

* Update surface area

* Fix xml doc test

* Update baselines

* Update src/Compiler/SyntaxTree/SyntaxTree.fsi

Co-authored-by: Edgar Gonzalez 

* Add MutableKeyword to SynFieldTrivia. (#11)

* Simplify

* Fantomas

---------

Co-authored-by: Edgar Gonzalez 
Co-authored-by: Florian Verdonck 

---------

Co-authored-by: Kevin Ransom (msft) 
Co-authored-by: Eugene Auduchinok 
Co-authored-by: Edgar Gonzalez 
Co-authored-by: Florian Verdonck 
Co-authored-by: Tomas Grosup 
---
 .../FSharp.Compiler.Service/8.0.200.md        |  3 +-
 src/Compiler/AbstractIL/ilread.fs             |  7 +-
 src/Compiler/Checking/CheckDeclarations.fs    | 34 +++++---
 src/Compiler/FSComp.txt                       |  3 +-
 src/Compiler/SyntaxTree/ParseHelpers.fs       | 71 +++++++++++++---
 src/Compiler/SyntaxTree/ParseHelpers.fsi      | 19 ++---
 src/Compiler/SyntaxTree/SyntaxTree.fs         |  4 +
 src/Compiler/SyntaxTree/SyntaxTree.fsi        |  3 +
 src/Compiler/SyntaxTree/SyntaxTrivia.fs       |  7 +-
 src/Compiler/SyntaxTree/SyntaxTrivia.fsi      |  2 +
 src/Compiler/pars.fsy                         | 83 +++++++++----------
 src/Compiler/xlf/FSComp.txt.cs.xlf            |  5 ++
 src/Compiler/xlf/FSComp.txt.de.xlf            |  5 ++
 src/Compiler/xlf/FSComp.txt.es.xlf            |  5 ++
 src/Compiler/xlf/FSComp.txt.fr.xlf            |  5 ++
 src/Compiler/xlf/FSComp.txt.it.xlf            |  5 ++
 src/Compiler/xlf/FSComp.txt.ja.xlf            |  5 ++
 src/Compiler/xlf/FSComp.txt.ko.xlf            |  5 ++
 src/Compiler/xlf/FSComp.txt.pl.xlf            |  5 ++
 src/Compiler/xlf/FSComp.txt.pt-BR.xlf         |  5 ++
 src/Compiler/xlf/FSComp.txt.ru.xlf            |  5 ++
 src/Compiler/xlf/FSComp.txt.tr.xlf            |  5 ++
 src/Compiler/xlf/FSComp.txt.zh-Hans.xlf       |  5 ++
 src/Compiler/xlf/FSComp.txt.zh-Hant.xlf       |  5 ++
 .../FieldMembers/FieldMembers.fs              |  8 +-
 .../Types/RecordTypes/AnonymousRecords.fs     |  2 +
 .../Language/StaticClassTests.fs              |  8 +-
 ...ervice.SurfaceArea.netstandard20.debug.bsl |  6 +-
 ...vice.SurfaceArea.netstandard20.release.bsl |  6 +-
 tests/fsharp/typecheck/sigs/neg16.bsl         |  2 +-
 tests/fsharp/typecheck/sigs/neg28.bsl         |  2 +-
 .../StructTypes/E_Regressions02b.fs           |  2 +-
 .../InteractiveSession/Misc/E_emptyRecord.fsx |  2 +-
 tests/service/XmlDocTests.fs                  |  2 +-
 .../Exception/Recover Function Type 01.fs.bsl |  6 +-
 .../LeadingKeyword/StaticValKeyword.fsi.bsl   |  5 +-
 .../LeadingKeyword/ValKeyword.fsi.bsl         |  5 +-
 .../data/SyntaxTree/Member/Field 01.fs.bsl    |  7 +-
 .../data/SyntaxTree/Member/Field 02.fs.bsl    | 13 +--
 .../data/SyntaxTree/Member/Field 03.fs.bsl    | 16 ++--
 .../data/SyntaxTree/Member/Field 04.fs.bsl    | 17 ++--
 .../data/SyntaxTree/Member/Field 05.fs.bsl    |  7 +-
 .../data/SyntaxTree/Member/Field 06.fs.bsl    | 14 ++--
 .../data/SyntaxTree/Member/Field 07.fs.bsl    | 14 ++--
 .../data/SyntaxTree/Member/Field 08.fs.bsl    |  9 +-
 .../data/SyntaxTree/Member/Field 09.fs.bsl    | 11 +--
 .../data/SyntaxTree/Member/Field 10.fs        |  6 ++
 .../data/SyntaxTree/Member/Field 10.fs.bsl    | 32 +++++++
 .../data/SyntaxTree/Member/Field 11.fs        |  6 ++
 .../data/SyntaxTree/Member/Field 11.fs.bsl    | 32 +++++++
 .../data/SyntaxTree/Member/Field 12.fs        |  6 ++
 .../data/SyntaxTree/Member/Field 12.fs.bsl    | 32 +++++++
 .../data/SyntaxTree/Member/Field 13.fs        |  6 ++
 .../data/SyntaxTree/Member/Field 13.fs.bsl    | 32 +++++++
 .../data/SyntaxTree/Member/Field 14.fs        |  6 ++
 .../data/SyntaxTree/Member/Field 14.fs.bsl    | 31 +++++++
 .../data/SyntaxTree/Member/Field 15.fs        |  7 ++
 .../data/SyntaxTree/Member/Field 15.fs.bsl    | 37 +++++++++
 ...spaceShouldStartAtNamespaceKeyword.fsi.bsl |  6 +-
 ...urnsRangeOfSynModuleOrNamespaceSig.fsi.bsl |  6 +-
 ...ShouldEndAtTheLastSynModuleSigDecl.fsi.bsl | 18 ++--
 ...xceptionDefnReprAndSynExceptionSig.fsi.bsl |  6 +-
 ...esShouldBeIncludedInRecursiveTypes.fsi.bsl |  3 +-
 ...ionSigAndSynModuleSigDeclException.fsi.bsl |  6 +-
 ...DefnSigRecordShouldEndAtLastMember.fsi.bsl |  3 +-
 ...ypeDefnSigSimpleShouldEndAtLastVal.fsi.bsl |  8 +-
 ...ionContainsTheRangeOfTheEqualsSign.fsi.bsl |  9 +-
 ...tesShouldBeIncludedInRecursiveTypes.fs.bsl |  9 +-
 .../SyntaxTree/Type/Record - Access 01.fs     |  8 ++
 .../SyntaxTree/Type/Record - Access 01.fs.bsl | 32 +++++++
 .../SyntaxTree/Type/Record - Access 02.fs     |  8 ++
 .../SyntaxTree/Type/Record - Access 02.fs.bsl | 33 ++++++++
 .../SyntaxTree/Type/Record - Access 03.fs     |  8 ++
 .../SyntaxTree/Type/Record - Access 03.fs.bsl | 33 ++++++++
 .../SyntaxTree/Type/Record - Access 04.fs     |  8 ++
 .../SyntaxTree/Type/Record - Access 04.fs.bsl | 32 +++++++
 .../SyntaxTree/Type/Record - Mutable 01.fs    |  8 ++
 .../Type/Record - Mutable 01.fs.bsl           | 32 +++++++
 .../SyntaxTree/Type/Record - Mutable 02.fs    |  9 ++
 .../Type/Record - Mutable 02.fs.bsl           | 38 +++++++++
 .../SyntaxTree/Type/Record - Mutable 03.fs    |  9 ++
 .../Type/Record - Mutable 03.fs.bsl           | 38 +++++++++
 .../SyntaxTree/Type/Record - Mutable 04.fs    | 10 +++
 .../Type/Record - Mutable 04.fs.bsl           | 44 ++++++++++
 .../SyntaxTree/Type/Record - Mutable 05.fs    | 10 +++
 .../Type/Record - Mutable 05.fs.bsl           | 43 ++++++++++
 .../data/SyntaxTree/Type/Record 01.fs.bsl     |  6 +-
 .../data/SyntaxTree/Type/Record 02.fs.bsl     |  6 +-
 .../service/data/SyntaxTree/Type/Record 03.fs |  6 ++
 .../data/SyntaxTree/Type/Record 03.fs.bsl     | 22 +++++
 .../service/data/SyntaxTree/Type/Record 04.fs |  8 ++
 .../data/SyntaxTree/Type/Record 04.fs.bsl     | 30 +++++++
 .../service/data/SyntaxTree/Type/Record 05.fs |  8 ++
 .../data/SyntaxTree/Type/Record 05.fs.bsl     | 42 ++++++++++
 .../data/SyntaxTree/Type/Struct 02.fs.bsl     |  7 +-
 ...ordContainsTheRangeOfTheWithKeyword.fs.bsl |  3 +-
 ...nionContainsTheRangeOfTheEqualsSign.fs.bsl |  9 +-
 .../UnionCase/Missing keyword of.fs.bsl       |  9 +-
 .../UnionCase/Missing name 03.fs.bsl          |  3 +-
 .../UnionCase/Missing name 04.fs.bsl          |  3 +-
 .../UnionCase/Missing name 05.fs.bsl          |  3 +-
 .../MultipleSynUnionCasesHaveBarRange.fs.bsl  |  6 +-
 .../UnionCase/PrivateKeywordHasRange.fs.bsl   |  3 +-
 .../UnionCase/Recover Function Type 01.fs.bsl |  3 +-
 .../UnionCase/Recover Function Type 02.fs.bsl |  3 +-
 .../UnionCase/Recover Function Type 03.fs.bsl |  3 +-
 .../SingleSynUnionCaseHasBarRange.fs.bsl      |  3 +-
 .../SingleSynUnionCaseWithoutBar.fs.bsl       |  3 +-
 .../UnionCaseFieldsCanHaveComments.fs.bsl     |  6 +-
 109 files changed, 1167 insertions(+), 203 deletions(-)
 create mode 100644 tests/service/data/SyntaxTree/Member/Field 10.fs
 create mode 100644 tests/service/data/SyntaxTree/Member/Field 10.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Member/Field 11.fs
 create mode 100644 tests/service/data/SyntaxTree/Member/Field 11.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Member/Field 12.fs
 create mode 100644 tests/service/data/SyntaxTree/Member/Field 12.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Member/Field 13.fs
 create mode 100644 tests/service/data/SyntaxTree/Member/Field 13.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Member/Field 14.fs
 create mode 100644 tests/service/data/SyntaxTree/Member/Field 14.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Member/Field 15.fs
 create mode 100644 tests/service/data/SyntaxTree/Member/Field 15.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Access 01.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Access 01.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Access 02.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Access 02.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Access 03.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Access 03.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Access 04.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Access 04.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Mutable 01.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Mutable 01.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Mutable 02.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Mutable 02.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Mutable 03.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Mutable 03.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Mutable 04.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Mutable 04.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Mutable 05.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Record - Mutable 05.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Record 03.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Record 03.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Record 04.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Record 04.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Record 05.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Record 05.fs.bsl

diff --git a/docs/release-notes/FSharp.Compiler.Service/8.0.200.md b/docs/release-notes/FSharp.Compiler.Service/8.0.200.md
index 33e81141302..c0d199a7864 100644
--- a/docs/release-notes/FSharp.Compiler.Service/8.0.200.md
+++ b/docs/release-notes/FSharp.Compiler.Service/8.0.200.md
@@ -1 +1,2 @@
-- Miscellaneous fixes to parens analysis - https://github.com/dotnet/fsharp/pull/16262
\ No newline at end of file
+- Miscellaneous fixes to parens analysis - https://github.com/dotnet/fsharp/pull/16262
+- Fixes #16359 - correctly handle imports with 0 length public key tokens - https://github.com/dotnet/fsharp/pull/16363
\ No newline at end of file
diff --git a/src/Compiler/AbstractIL/ilread.fs b/src/Compiler/AbstractIL/ilread.fs
index 03dbb67bbc4..6dcc4ee33c6 100644
--- a/src/Compiler/AbstractIL/ilread.fs
+++ b/src/Compiler/AbstractIL/ilread.fs
@@ -1946,7 +1946,12 @@ and seekReadAssemblyManifest (ctxt: ILMetadataReader) pectxt idx =
         Name = name
         AuxModuleHashAlgorithm = hash
         SecurityDeclsStored = ctxt.securityDeclsReader_Assembly
-        PublicKey = pubkey
+        PublicKey =
+            // The runtime and C# treat a 0 length publicKey as an unsigned assembly, so if a public record exists with a length of 0
+            // treat it as unsigned
+            match pubkey with
+            | Some pkBytes when pkBytes.Length > 0 -> pubkey
+            | _ -> None
         Version = Some(ILVersionInfo(v1, v2, v3, v4))
         Locale = readStringHeapOption ctxt localeIdx
         CustomAttrsStored = ctxt.customAttrsReader_Assembly
diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs
index c93b67e2118..2b5c491daca 100644
--- a/src/Compiler/Checking/CheckDeclarations.fs
+++ b/src/Compiler/Checking/CheckDeclarations.fs
@@ -423,8 +423,9 @@ module TcRecdUnionAndEnumDeclarations =
         let vis = CombineReprAccess parent vis
         Construct.NewRecdField isStatic konst id nameGenerated tyR isMutable vol attrsForProperty attrsForField xmldoc vis false
 
-    let TcFieldDecl (cenv: cenv) env parent isIncrClass tpenv (isStatic, synAttrs, id, nameGenerated, ty, isMutable, xmldoc, vis, m) =
+    let TcFieldDecl (cenv: cenv) env parent isIncrClass tpenv (isStatic, synAttrs, id: Ident, nameGenerated, ty, isMutable, xmldoc, vis) =
         let g = cenv.g
+        let m = id.idRange
         let attrs, _ = TcAttributesWithPossibleTargets false cenv env AttributeTargets.FieldDecl synAttrs
         let attrsForProperty, attrsForField = attrs |> List.partition (fun (attrTargets, _) -> (attrTargets &&& AttributeTargets.Property) <> enum 0) 
         let attrsForProperty = (List.map snd attrsForProperty) 
@@ -458,18 +459,20 @@ module TcRecdUnionAndEnumDeclarations =
 
         let checkXmlDocs = cenv.diagnosticOptions.CheckXmlDocs
         let xmlDoc = xmldoc.ToXmlDoc(checkXmlDocs, Some [])
-        TcFieldDecl cenv env parent false tpenv (isStatic, attribs, id, idOpt.IsNone, ty, isMutable, xmlDoc, vis, m)
+        TcFieldDecl cenv env parent false tpenv (isStatic, attribs, id, idOpt.IsNone, ty, isMutable, xmlDoc, vis)
 
     let TcNamedFieldDecl cenv env parent isIncrClass tpenv (SynField(Attributes attribs, isStatic, id, ty, isMutable, xmldoc, vis, m, _)) =
         match id with 
-        | None -> error (Error(FSComp.SR.tcFieldRequiresName(), m))
+        | None ->
+            errorR (Error(FSComp.SR.tcFieldRequiresName(), m))
+            None
         | Some id ->
             let checkXmlDocs = cenv.diagnosticOptions.CheckXmlDocs
             let xmlDoc = xmldoc.ToXmlDoc(checkXmlDocs, Some [])
-            TcFieldDecl cenv env parent isIncrClass tpenv (isStatic, attribs, id, false, ty, isMutable, xmlDoc, vis, m) 
+            Some(TcFieldDecl cenv env parent isIncrClass tpenv (isStatic, attribs, id, false, ty, isMutable, xmlDoc, vis)) 
 
     let TcNamedFieldDecls cenv env parent isIncrClass tpenv fields =
-        fields |> List.map (TcNamedFieldDecl cenv env parent isIncrClass tpenv) 
+        fields |> List.choose (TcNamedFieldDecl cenv env parent isIncrClass tpenv) 
 
     //-------------------------------------------------------------------------
     // Bind other elements of type definitions (constructors etc.)
@@ -518,14 +521,19 @@ module TcRecdUnionAndEnumDeclarations =
             match args with
             | SynUnionCaseKind.Fields flds -> 
                 let nFields = flds.Length
-                let rfields = flds |> List.mapi (fun i (SynField (idOpt = idOpt) as fld) ->
-                    match idOpt, parent with
-                    | Some fieldId, Parent tcref ->
-                        let item = Item.UnionCaseField (UnionCaseInfo (thisTyInst, UnionCaseRef (tcref, id.idText)), i)
-                        CallNameResolutionSink cenv.tcSink (fieldId.idRange, env.NameEnv, item, emptyTyparInst, ItemOccurence.Binding, env.AccessRights)
-                        TcNamedFieldDecl cenv env parent false tpenv fld
-                    | _ ->
-                        TcAnonFieldDecl cenv env parent tpenv (mkUnionCaseFieldName nFields i) fld)
+                let rfields =
+                    flds
+                    |> List.mapi (fun i (SynField (idOpt = idOpt) as fld) ->
+                        match idOpt, parent with
+                        | Some fieldId, Parent tcref ->
+                            let item = Item.UnionCaseField (UnionCaseInfo (thisTyInst, UnionCaseRef (tcref, id.idText)), i)
+                            CallNameResolutionSink cenv.tcSink (fieldId.idRange, env.NameEnv, item, emptyTyparInst, ItemOccurence.Binding, env.AccessRights)
+                            TcNamedFieldDecl cenv env parent false tpenv fld
+                        | _ ->
+                            Some(TcAnonFieldDecl cenv env parent tpenv (mkUnionCaseFieldName nFields i) fld)
+                    )
+                    |> List.choose (fun x -> x)
+                
                 ValidateFieldNames(flds, rfields)
                 
                 rfields, thisTy
diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt
index 833a9e12c9e..313a0b61e64 100644
--- a/src/Compiler/FSComp.txt
+++ b/src/Compiler/FSComp.txt
@@ -1748,4 +1748,5 @@ featureReuseSameFieldsInStructUnions,"Share underlying fields in a [] di
 3859,tcNoStaticPropertyFoundForOverride,"No static abstract property was found that corresponds to this override"
 3860,chkStaticMembersOnObjectExpressions,"Object expressions cannot implement interfaces with static abstract members or declare static members."
 3861,chkTailCallAttrOnNonRec,"The TailCall attribute should only be applied to recursive functions."
-3862,parsStaticMemberImcompleteSyntax,"Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration."
\ No newline at end of file
+3862,parsStaticMemberImcompleteSyntax,"Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration."
+3863,parsExpectingField,"Expecting record field"
\ No newline at end of file
diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs
index fed1e4c924e..bb2e7755767 100644
--- a/src/Compiler/SyntaxTree/ParseHelpers.fs
+++ b/src/Compiler/SyntaxTree/ParseHelpers.fs
@@ -1140,20 +1140,71 @@ let mkAutoPropDefn mVal access ident typ mEquals (expr: SynExpr) accessors xmlDo
         trivia
     )
 
-let mkValField mVal mRhs mut access ident (typ: SynType) xmlDoc rangeStart attribs mStaticOpt =
-    let isStatic = Option.isSome mStaticOpt
-    let mValDecl = unionRanges rangeStart typ.Range |> unionRangeWithXmlDoc xmlDoc
+let mkSynField
+    parseState
+    (idOpt: Ident option)
+    (t: SynType option)
+    (isMutable: range option)
+    (vis: SynAccess option)
+    (attributes: SynAttributes)
+    (mStatic: range option)
+    (rangeStart: range)
+    (leadingKeyword: SynLeadingKeyword option)
+    =
+
+    let t, mStart =
+        match t with
+        | Some value -> value, rangeStart
+        | None ->
+
+            let mType, mStart =
+                idOpt
+                |> Option.map _.idRange
+                |> Option.orElseWith (fun _ -> vis |> Option.map (fun v -> v.Range))
+                |> Option.orElse isMutable
+                |> Option.orElseWith (fun _ -> leadingKeyword |> Option.map (fun k -> k.Range))
+                |> Option.orElseWith (fun _ -> attributes |> List.tryLast |> Option.map (fun l -> l.Range))
+                |> Option.map (fun m -> m, rangeStart)
+                |> Option.defaultWith (fun _ -> rangeStart.StartRange, rangeStart.StartRange)
+
+            SynType.FromParseError(mType.EndRange), mStart
+
+    let mWhole = unionRanges mStart t.Range
+    let xmlDoc = grabXmlDocAtRangeStart (parseState, attributes, mWhole)
+    let mWhole = unionRangeWithXmlDoc xmlDoc mWhole
+
+    SynField(
+        attributes,
+        Option.isSome mStatic,
+        idOpt,
+        t,
+        Option.isSome isMutable,
+        xmlDoc,
+        vis,
+        mWhole,
+        {
+            LeadingKeyword = leadingKeyword
+            MutableKeyword = isMutable
+        }
+    )
 
+let mkValField
+    parseState
+    mVal
+    (isMutable: range option)
+    access
+    (idOpt: Ident option)
+    (typ: SynType option)
+    (rangeStart: range)
+    attribs
+    mStaticOpt
+    =
     let leadingKeyword =
         match mStaticOpt with
         | None -> SynLeadingKeyword.Val mVal
         | Some mStatic -> SynLeadingKeyword.StaticVal(mStatic, mVal)
 
-    let fld =
-        SynField(attribs, isStatic, Some ident, typ, mut, xmlDoc, access, mRhs, { LeadingKeyword = Some leadingKeyword })
+    let field =
+        mkSynField parseState idOpt typ isMutable access attribs mStaticOpt rangeStart (Some leadingKeyword)
 
-    SynMemberDefn.ValField(fld, mValDecl)
-
-let mkSynField parseState idOpt t isMutable vis attributes isStatic mWhole leadingKeyword =
-    let xmlDoc = grabXmlDocAtRangeStart (parseState, attributes, mWhole)
-    SynField(attributes, isStatic, idOpt, t, isMutable, xmlDoc, vis, mWhole, { LeadingKeyword = leadingKeyword })
+    SynMemberDefn.ValField(field, field.Range)
diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fsi b/src/Compiler/SyntaxTree/ParseHelpers.fsi
index 02b844894cb..9add16af683 100644
--- a/src/Compiler/SyntaxTree/ParseHelpers.fsi
+++ b/src/Compiler/SyntaxTree/ParseHelpers.fsi
@@ -280,14 +280,13 @@ val mkAutoPropDefn:
                 SynMemberDefn
 
 val mkValField:
+    parseState: IParseState ->
     mVal: range ->
-    mRhs: range ->
-    mut: bool ->
+    isMutable: range option ->
     access: SynAccess option ->
-    ident: Ident ->
-    typ: SynType ->
-    xmlDoc: PreXmlDoc ->
-    range ->
+    idOpt: Ident option ->
+    typ: SynType option ->
+    rangeStart: range ->
     SynAttributes ->
     range option ->
         SynMemberDefn
@@ -295,11 +294,11 @@ val mkValField:
 val mkSynField:
     parseState: IParseState ->
     idOpt: Ident option ->
-    t: SynType ->
-    isMutable: bool ->
+    t: SynType option ->
+    isMutable: range option ->
     vis: SynAccess option ->
     attributes: SynAttributeList list ->
-    isStatic: bool ->
-    mWhole: range ->
+    mStatic: range option ->
+    rangeStart: range ->
     leadingKeyword: SynLeadingKeyword option ->
         SynField
diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs
index 4b413937cb2..d47b2620b44 100644
--- a/src/Compiler/SyntaxTree/SyntaxTree.fs
+++ b/src/Compiler/SyntaxTree/SyntaxTree.fs
@@ -1297,6 +1297,10 @@ type SynField =
         range: range *
         trivia: SynFieldTrivia
 
+    member this.Range =
+        match this with
+        | SynField(range = range) -> range
+
 []
 type SynComponentInfo =
     | SynComponentInfo of
diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi
index 808692106e4..63ebdc6e448 100644
--- a/src/Compiler/SyntaxTree/SyntaxTree.fsi
+++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi
@@ -1461,6 +1461,9 @@ type SynField =
         range: range *
         trivia: SynFieldTrivia
 
+    /// Gets the syntax range of this construct
+    member Range: range
+
 /// Represents the syntax tree associated with the name of a type definition or module
 /// in signature or implementation.
 ///
diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fs b/src/Compiler/SyntaxTree/SyntaxTrivia.fs
index 623e07fa1ff..7330ac9b695 100644
--- a/src/Compiler/SyntaxTree/SyntaxTrivia.fs
+++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fs
@@ -383,9 +383,14 @@ type SynMemberDefnAbstractSlotTrivia =
 type SynFieldTrivia =
     {
         LeadingKeyword: SynLeadingKeyword option
+        MutableKeyword: range option
     }
 
-    static member Zero: SynFieldTrivia = { LeadingKeyword = None }
+    static member Zero: SynFieldTrivia =
+        {
+            LeadingKeyword = None
+            MutableKeyword = None
+        }
 
 []
 type SynTypeOrTrivia = { OrKeyword: range }
diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi
index d30816e697b..137f5432803 100644
--- a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi
+++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi
@@ -486,6 +486,8 @@ type SynFieldTrivia =
     {
         /// Used leading keyword of SynField
         LeadingKeyword: SynLeadingKeyword option
+        /// The syntax range of the `mutable` keyword
+        MutableKeyword: range option
     }
 
     static member Zero: SynFieldTrivia
diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy
index a0af31e4e6a..03e8c099e25 100644
--- a/src/Compiler/pars.fsy
+++ b/src/Compiler/pars.fsy
@@ -730,7 +730,7 @@ moduleSpfn:
 valSpfn:
   | opt_attributes opt_access VAL opt_attributes opt_inline opt_mutable opt_access nameop opt_explicitValTyparDecls COLON topTypeWithTypeConstraints optLiteralValueSpfn
       { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2))
-        let attr1, attr2, isInline, isMutable, vis2, id, doc, explicitValTyparDecls, (ty, arity), (mEquals, konst: SynExpr option) = ($1), ($4), (Option.isSome $5), ($6), ($7), ($8), grabXmlDoc(parseState, $1, 1), ($9), ($11), ($12)
+        let attr1, attr2, isInline, isMutable, vis2, id, doc, explicitValTyparDecls, (ty, arity), (mEquals, konst: SynExpr option) = ($1), ($4), (Option.isSome $5), (Option.isSome $6), ($7), ($8), grabXmlDoc(parseState, $1, 1), ($9), ($11), ($12)
         if not (isNil attr2) then errorR(Deprecated(FSComp.SR.parsAttributesMustComeBeforeVal(), rhs parseState 4))
         let m =
             rhs2 parseState 1 11
@@ -987,21 +987,23 @@ classMemberSpfn:
        SynMemberSig.Inherit(ty, unionRanges (rhs parseState 1) mInherit) }
 
   | opt_attributes opt_access VAL fieldDecl
-     { let mWhole = rhs2 parseState 1 4
-       if Option.isSome $2 then errorR (Error (FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier (), rhs parseState 2))
+     { if Option.isSome $2 then
+           errorR (Error (FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier (), rhs parseState 2))
+       let mStart = rhs parseState 1
        let mVal = rhs parseState 3
-       let (SynField(xmlDoc = xmlDoc)) as field = $4 $1 false mWhole (Some(SynLeadingKeyword.Val mVal))
-       let mWhole = unionRangeWithXmlDoc xmlDoc mWhole
-       SynMemberSig.ValField(field, mWhole) }
+       let leadingKeyword = Some(SynLeadingKeyword.Val mVal)
+       let (SynField(xmlDoc = xmlDoc; range = range)) as field = $4 $1 None mStart leadingKeyword
+       SynMemberSig.ValField(field, range) }
 
   | opt_attributes opt_access STATIC VAL fieldDecl
-     { let mWhole = rhs2 parseState 1 5
-       if Option.isSome $2 then errorR (Error (FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier (), rhs parseState 2))
+     { if Option.isSome $2 then
+           errorR (Error (FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier (), rhs parseState 2))
+       let mStart = rhs parseState 1
        let mStatic = rhs parseState 3
        let mVal = rhs parseState 4
-       let (SynField(xmlDoc = xmlDoc)) as field = $5 $1 true mWhole (Some(SynLeadingKeyword.StaticVal(mStatic, mVal)))
-       let mWhole = unionRangeWithXmlDoc xmlDoc mWhole
-       SynMemberSig.ValField(field, mWhole) }
+       let leadingKeyword = Some(SynLeadingKeyword.StaticVal(mStatic, mVal))
+       let (SynField(xmlDoc = xmlDoc; range = range)) as field = $5 $1 (Some mStatic) mStart leadingKeyword
+       SynMemberSig.ValField(field, range) }
 
   | opt_attributes opt_access STATIC typeKeyword tyconSpfn
      { let leadingKeyword = SynTypeDefnLeadingKeyword.StaticType(rhs parseState 3, rhs parseState 4)
@@ -2126,38 +2128,26 @@ classDefnMember:
 valDefnDecl:
   | VAL opt_mutable opt_access ident COLON typ
      { let mVal = rhs parseState 1
-       let mRhs = rhs2 parseState 4 6
        fun rangeStart attribs mStaticOpt ->
-           let xmlDoc = grabXmlDocAtRangeStart (parseState, attribs, rangeStart)
-           [ mkValField mVal mRhs $2 $3 $4 $6 xmlDoc rangeStart attribs mStaticOpt ] }
+           [ mkValField parseState mVal $2 $3 (Some $4) (Some $6) rangeStart attribs mStaticOpt ] }
 
   | VAL opt_mutable opt_access ident COLON recover
      { let mVal = rhs parseState 1
-       let mRhs = rhs2 parseState 4 6
        let mColon = rhs parseState 5
        let ty = SynType.FromParseError(mColon.EndRange)
        fun rangeStart attribs mStaticOpt ->
-           let xmlDoc = grabXmlDocAtRangeStart (parseState, attribs, rangeStart)
-           [ mkValField mVal mRhs $2 $3 $4 ty xmlDoc rangeStart attribs mStaticOpt ] }
+           [ mkValField parseState mVal $2 $3 (Some $4) (Some ty) rangeStart attribs mStaticOpt ] }
 
   | VAL opt_mutable opt_access ident recover
      { let mVal = rhs parseState 1
-       let mRhs = rhs2 parseState 4 6
-       let mColon = rhs parseState 5
-       let ty = SynType.FromParseError(mColon.EndRange)
+       let ty = SynType.FromParseError($4.idRange.EndRange)
        fun rangeStart attribs mStaticOpt ->
-           let xmlDoc = grabXmlDocAtRangeStart (parseState, attribs, rangeStart)
-           [ mkValField mVal mRhs $2 $3 $4 ty xmlDoc rangeStart attribs mStaticOpt ] }
+           [ mkValField parseState mVal $2 $3 (Some $4) (Some ty) rangeStart attribs mStaticOpt ] }
 
   | VAL opt_mutable opt_access recover
      { let mVal = rhs parseState 1
-       let mRhs = rhs2 parseState 4 6
-       let id = mkSynId mVal.EndRange ""
-       let mColon = rhs parseState 5
-       let ty = SynType.FromParseError(mColon.EndRange)
        fun rangeStart attribs mStaticOpt ->
-           let xmlDoc = grabXmlDocAtRangeStart (parseState, attribs, rangeStart)
-           [ mkValField mVal mRhs $2 $3 id ty xmlDoc rangeStart attribs mStaticOpt ] }
+           [ mkValField parseState mVal $2 $3 None None rangeStart attribs mStaticOpt ] }
 
 
 /* An auto-property definition in an object type definition */
@@ -2165,7 +2155,7 @@ autoPropsDefnDecl:
   | VAL opt_mutable opt_access ident opt_typ EQUALS typedSequentialExprBlock classMemberSpfnGetSet
      { let mVal = rhs parseState 1
        let mEquals = rhs parseState 6
-       if $2 then
+       if Option.isSome $2 then
            errorR (Error(FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet (), rhs parseState 2))
        fun attribs flags rangeStart ->
            let xmlDoc = grabXmlDocAtRangeStart (parseState, attribs, rangeStart)
@@ -2178,7 +2168,7 @@ autoPropsDefnDecl:
            | Some t -> t.Range
            | _ -> $4.idRange
        let expr = arbExpr ("autoProp1", mEnd.EndRange)
-       if $2 then
+       if Option.isSome $2 then
            errorR (Error(FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet (), rhs parseState 2))
        fun attribs flags rangeStart ->
            let xmlDoc = grabXmlDocAtRangeStart (parseState, attribs, rangeStart)
@@ -2191,7 +2181,7 @@ autoPropsDefnDecl:
            | Some t -> t.Range
            | _ -> $4.idRange
        let expr = arbExpr ("autoProp2", mEnd.EndRange)
-       if $2 then
+       if Option.isSome $2 then
            errorR (Error(FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet (), rhs parseState 2))
        fun attribs flags rangeStart ->
            let xmlDoc = grabXmlDocAtRangeStart (parseState, attribs, rangeStart)
@@ -2201,7 +2191,7 @@ autoPropsDefnDecl:
      { let mVal = rhs parseState 1
        let id = mkSynId mVal.EndRange ""
        let expr = arbExpr ("autoProp3", mVal.EndRange)
-       if $2 then
+       if Option.isSome $2 then
            errorR (Error(FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet (), rhs parseState 2))
        fun attribs flags rangeStart ->
            let xmlDoc = grabXmlDocAtRangeStart(parseState, attribs, rangeStart)
@@ -2455,6 +2445,10 @@ braceFieldDeclList:
   | LBRACE error rbrace
      { [] }
 
+  | LBRACE rbrace
+     { errorR (Error(FSComp.SR.parsExpectingField(), rhs parseState 2))
+       [] }
+
 anonRecdType:
     | STRUCT braceBarFieldDeclListCore
         { $2, true }
@@ -2838,8 +2832,8 @@ recdFieldDeclList:
 /* A field declaration in a record type */
 recdFieldDecl:
   | opt_attributes fieldDecl
-     { let mWhole = rhs2 parseState 1 2
-       let fld = $2 $1 false mWhole None
+     { let rangeStart = rhs parseState 1
+       let fld = $2 $1 None rangeStart None
        let (SynField (a, b, c, d, e, xmlDoc, vis, mWhole, trivia)) = fld
        if Option.isSome vis then errorR (Error (FSComp.SR.parsRecordFieldsCannotHaveVisibilityDeclarations (), rhs parseState 2))
        let mWhole = unionRangeWithXmlDoc xmlDoc mWhole
@@ -2848,14 +2842,19 @@ recdFieldDecl:
 /* Part of a field or val declaration in a record type or object type */
 fieldDecl:
   | opt_mutable opt_access ident COLON typ
-     { mkSynField parseState (Some $3) $5 $1 $2 }
+     { mkSynField parseState (Some $3) (Some $5) $1 $2 }
+
   | opt_mutable opt_access ident COLON recover
      { let mColon = rhs parseState 4
        let t = SynType.FromParseError(mColon.EndRange)
-       mkSynField parseState (Some $3) t $1 $2 }
+       mkSynField parseState (Some $3) (Some t) $1 $2 }
+
   | opt_mutable opt_access ident recover
      { let t = SynType.FromParseError($3.idRange.EndRange)
-       mkSynField parseState (Some $3) t $1 $2 }
+       mkSynField parseState (Some $3) (Some t) $1 $2 }
+
+  | opt_mutable opt_access recover
+     { mkSynField parseState None None $1 $2 }
 
 /* An exception definition */
 exconDefn:
@@ -3200,7 +3199,7 @@ localBinding:
             let spBind = if IsDebugPointBinding bindingPat expr then DebugPointAtBinding.Yes mWhole else DebugPointAtBinding.NoneAtLet
             let mWholeBindLhs = (mBindLhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range)
             let trivia: SynBindingTrivia = { LeadingKeyword = leadingKeyword; InlineKeyword = $1; EqualsRange = Some mEquals }
-            mkSynBinding (xmlDoc, bindingPat) (vis, Option.isSome $1, $2, mWholeBindLhs, spBind, optReturnType, expr, mRhs, opts, attrs, None, trivia))
+            mkSynBinding (xmlDoc, bindingPat) (vis, Option.isSome $1, Option.isSome $2, mWholeBindLhs, spBind, optReturnType, expr, mRhs, opts, attrs, None, trivia))
         localBindingRange, localBindingBuilder }
 
   | opt_inline opt_mutable bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS error
@@ -3215,7 +3214,7 @@ localBinding:
             let rhsExpr = arbExpr ("localBinding1", zeroWidthAtEnd)
             let spBind = if IsDebugPointBinding bindingPat rhsExpr then DebugPointAtBinding.Yes mWhole else DebugPointAtBinding.NoneAtLet
             let trivia: SynBindingTrivia = { LeadingKeyword = leadingKeyword; InlineKeyword = $1; EqualsRange = Some mEquals }
-            mkSynBinding (xmlDoc, bindingPat) (vis, Option.isSome $1, $2, mBindLhs, spBind, optReturnType, rhsExpr, mRhs, [], attrs, None, trivia))
+            mkSynBinding (xmlDoc, bindingPat) (vis, Option.isSome $1, Option.isSome $2, mBindLhs, spBind, optReturnType, rhsExpr, mRhs, [], attrs, None, trivia))
         mWhole, localBindingBuilder }
 
   | opt_inline opt_mutable bindingPattern opt_topReturnTypeWithTypeConstraints recover
@@ -3229,7 +3228,7 @@ localBinding:
             let spBind = DebugPointAtBinding.Yes(unionRanges leadingKeyword.Range mRhs)
             let trivia = { LeadingKeyword = leadingKeyword; InlineKeyword = $1; EqualsRange = None }
             let rhsExpr = arbExpr ("localBinding2", mRhs)
-            mkSynBinding (xmlDoc, bindingPat) (vis, Option.isSome $1, $2, mBindLhs, spBind, optReturnType, rhsExpr, mRhs, [], attrs, None, trivia))
+            mkSynBinding (xmlDoc, bindingPat) (vis, Option.isSome $1, Option.isSome $2, mBindLhs, spBind, optReturnType, rhsExpr, mRhs, [], attrs, None, trivia))
         mWhole, localBindingBuilder }
 
 /* A single expression with an optional type annotation, and an optional static optimization block */
@@ -6733,8 +6732,8 @@ opt_inline:
   | /* EMPTY */ { None }
 
 opt_mutable:
-  | MUTABLE { true }
-  | /* EMPTY */ { false }
+  | MUTABLE { Some(rhs parseState 1) }
+  | /* EMPTY */ { None }
 
 /* A 'do' token in either #light or non-#light */
 doToken:
diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf
index bf516029c79..dd6bb7e4a8b 100644
--- a/src/Compiler/xlf/FSComp.txt.cs.xlf
+++ b/src/Compiler/xlf/FSComp.txt.cs.xlf
@@ -937,6 +937,11 @@
         Byl očekáván výraz.
         
       
+      
+        Expecting record field
+        Expecting record field
+        
+      
       
         Expecting pattern
         Očekává se vzorek.
diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf
index 22802ae265c..5709590e6e1 100644
--- a/src/Compiler/xlf/FSComp.txt.de.xlf
+++ b/src/Compiler/xlf/FSComp.txt.de.xlf
@@ -937,6 +937,11 @@
         Ausdruck wird erwartet
         
       
+      
+        Expecting record field
+        Expecting record field
+        
+      
       
         Expecting pattern
         Muster wird erwartet
diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf
index ccfe10fe3ed..50fa09cf48d 100644
--- a/src/Compiler/xlf/FSComp.txt.es.xlf
+++ b/src/Compiler/xlf/FSComp.txt.es.xlf
@@ -937,6 +937,11 @@
         Se espera una expresión
         
       
+      
+        Expecting record field
+        Expecting record field
+        
+      
       
         Expecting pattern
         Se espera un patrón
diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf
index dfa91f3993a..0b62ce81f60 100644
--- a/src/Compiler/xlf/FSComp.txt.fr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.fr.xlf
@@ -937,6 +937,11 @@
          Expression attendue
         
       
+      
+        Expecting record field
+        Expecting record field
+        
+      
       
         Expecting pattern
         Modèle attendu
diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf
index 68fb9346530..a8eebb772c2 100644
--- a/src/Compiler/xlf/FSComp.txt.it.xlf
+++ b/src/Compiler/xlf/FSComp.txt.it.xlf
@@ -937,6 +937,11 @@
         Prevista espressione.
         
       
+      
+        Expecting record field
+        Expecting record field
+        
+      
       
         Expecting pattern
         Criterio previsto
diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf
index f5e65ed95de..962690cddbe 100644
--- a/src/Compiler/xlf/FSComp.txt.ja.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ja.xlf
@@ -937,6 +937,11 @@
         式を指定してください
         
       
+      
+        Expecting record field
+        Expecting record field
+        
+      
       
         Expecting pattern
         必要なパターン
diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf
index f1288c6468c..180dc864773 100644
--- a/src/Compiler/xlf/FSComp.txt.ko.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ko.xlf
@@ -937,6 +937,11 @@
         식이 필요함
         
       
+      
+        Expecting record field
+        Expecting record field
+        
+      
       
         Expecting pattern
         예상되는 패턴
diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf
index c2cdd82ba1a..cc5f2cf60a1 100644
--- a/src/Compiler/xlf/FSComp.txt.pl.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pl.xlf
@@ -937,6 +937,11 @@
         Oczekiwanie na wyrażenie
         
       
+      
+        Expecting record field
+        Expecting record field
+        
+      
       
         Expecting pattern
         Oczekiwano wzorca
diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
index 4bc1ebbc97e..a8c3dfa0fbe 100644
--- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
@@ -937,6 +937,11 @@
         Esperando uma expressão
         
       
+      
+        Expecting record field
+        Expecting record field
+        
+      
       
         Expecting pattern
         Padrão esperado
diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf
index f61866893f6..ad6ebab7293 100644
--- a/src/Compiler/xlf/FSComp.txt.ru.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ru.xlf
@@ -937,6 +937,11 @@
         Ожидается выражение
         
       
+      
+        Expecting record field
+        Expecting record field
+        
+      
       
         Expecting pattern
         Ожидается шаблон
diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf
index 4fe050cae41..968dcd472a7 100644
--- a/src/Compiler/xlf/FSComp.txt.tr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.tr.xlf
@@ -937,6 +937,11 @@
         İfade bekleniyor
         
       
+      
+        Expecting record field
+        Expecting record field
+        
+      
       
         Expecting pattern
         Desen bekleniyor
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
index 3bc0cb8f8dd..e01c25b21cb 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
@@ -937,6 +937,11 @@
         应为表达式
         
       
+      
+        Expecting record field
+        Expecting record field
+        
+      
       
         Expecting pattern
         预期模式
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
index b5fa1d13afb..5a20ba9eaf5 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
@@ -937,6 +937,11 @@
         必須是運算式
         
       
+      
+        Expecting record field
+        Expecting record field
+        
+      
       
         Expecting pattern
         必須是模式
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/FieldMembers/FieldMembers.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/FieldMembers/FieldMembers.fs
index 4ccc4a9b8cd..138cf45e723 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/FieldMembers/FieldMembers.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/FieldMembers/FieldMembers.fs
@@ -34,8 +34,8 @@ module FieldMembers =
         |> verifyCompile
         |> shouldFail
         |> withDiagnostics [
-            (Error 880, Line 11, Col 20, Line 11, Col 33, "Uninitialized 'val' fields must be mutable and marked with the '[]' attribute. Consider using a 'let' binding instead of a 'val' field.")
-            (Error 881, Line 11, Col 20, Line 11, Col 33, "Static 'val' fields in types must be mutable, private and marked with the '[]' attribute. They are initialized to the 'null' or 'zero' value for their type. Consider also using a 'static let mutable' binding in a class type.")
+            (Error 880, Line 11, Col 20, Line 11, Col 27, "Uninitialized 'val' fields must be mutable and marked with the '[]' attribute. Consider using a 'let' binding instead of a 'val' field.")
+            (Error 881, Line 11, Col 20, Line 11, Col 27, "Static 'val' fields in types must be mutable, private and marked with the '[]' attribute. They are initialized to the 'null' or 'zero' value for their type. Consider also using a 'static let mutable' binding in a class type.")
         ]
 
     // SOURCE=E_StaticField02a.fs	# E_StaticField02a.fs
@@ -45,8 +45,8 @@ module FieldMembers =
         |> verifyCompile
         |> shouldFail
         |> withDiagnostics [
-            (Error 881, Line 7, Col 32, Line 7, Col 49, "Static 'val' fields in types must be mutable, private and marked with the '[]' attribute. They are initialized to the 'null' or 'zero' value for their type. Consider also using a 'static let mutable' binding in a class type.")
-            (Error 881, Line 16, Col 32, Line 16, Col 49, "Static 'val' fields in types must be mutable, private and marked with the '[]' attribute. They are initialized to the 'null' or 'zero' value for their type. Consider also using a 'static let mutable' binding in a class type.")
+            (Error 881, Line 7, Col 32, Line 7, Col 40, "Static 'val' fields in types must be mutable, private and marked with the '[]' attribute. They are initialized to the 'null' or 'zero' value for their type. Consider also using a 'static let mutable' binding in a class type.")
+            (Error 881, Line 16, Col 32, Line 16, Col 40, "Static 'val' fields in types must be mutable, private and marked with the '[]' attribute. They are initialized to the 'null' or 'zero' value for their type. Consider also using a 'static let mutable' binding in a class type.")
         ]
 
     // SOURCE=StaticField01.fs		# StaticField01.fs
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs
index 6fa51549e91..354539ed7c1 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs
@@ -159,7 +159,9 @@ type ErrorResponse =
         |> withDiagnostics [
             Error 10, Line 5, Col 42, Line 5, Col 43, "Unexpected integer literal in field declaration. Expected ':' or other token."
             Error 10, Line 7, Col 12, Line 7, Col 14, "Unexpected symbol '|}' in field declaration. Expected identifier or other token."
+            Error 3244, Line 7, Col 9, Line 7, Col 14, "Invalid anonymous record type"
             Error 10, Line 10, Col 17, Line 10, Col 21, "Incomplete structured construct at or before this point in field declaration. Expected identifier or other token."
+            Error 3244, Line 10, Col 14, Line 11, Col 36, "Invalid anonymous record type"
         ]
         
     []
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/StaticClassTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/StaticClassTests.fs
index 6fc05018271..b28c96ccf51 100644
--- a/tests/FSharp.Compiler.ComponentTests/Language/StaticClassTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Language/StaticClassTests.fs
@@ -650,8 +650,8 @@ type B() =
          |> compile
          |> shouldFail
          |> withDiagnostics [
-             (Error 880, Line 4, Col 9, Line 4, Col 16, "Uninitialized 'val' fields must be mutable and marked with the '[]' attribute. Consider using a 'let' binding instead of a 'val' field.")
-             (Error 880, Line 5, Col 17, Line 5, Col 24, "Uninitialized 'val' fields must be mutable and marked with the '[]' attribute. Consider using a 'let' binding instead of a 'val' field.")
+             (Error 880, Line 4, Col 9, Line 4, Col 10, "Uninitialized 'val' fields must be mutable and marked with the '[]' attribute. Consider using a 'let' binding instead of a 'val' field.")
+             (Error 880, Line 5, Col 17, Line 5, Col 18, "Uninitialized 'val' fields must be mutable and marked with the '[]' attribute. Consider using a 'let' binding instead of a 'val' field.")
          ]
 
     []
@@ -682,8 +682,8 @@ type B() =
          |> compile
          |> shouldFail
          |> withDiagnostics [
-             (Error 880, Line 4, Col 9, Line 4, Col 16, "Uninitialized 'val' fields must be mutable and marked with the '[]' attribute. Consider using a 'let' binding instead of a 'val' field.")
-             (Error 880, Line 5, Col 17, Line 5, Col 24, "Uninitialized 'val' fields must be mutable and marked with the '[]' attribute. Consider using a 'let' binding instead of a 'val' field.")
+             (Error 880, Line 4, Col 9, Line 4, Col 10, "Uninitialized 'val' fields must be mutable and marked with the '[]' attribute. Consider using a 'let' binding instead of a 'val' field.")
+             (Error 880, Line 5, Col 17, Line 5, Col 18, "Uninitialized 'val' fields must be mutable and marked with the '[]' attribute. Consider using a 'let' binding instead of a 'val' field.")
              (Warning 3558, Line 4, Col 9, Line 4, Col 10, "If a type uses both [] and [] attributes, it means it is static. Explicit field declarations are not allowed.")
              (Warning 3558, Line 5, Col 17, Line 5, Col 18, "If a type uses both [] and [] attributes, it means it is static. Explicit field declarations are not allowed.")
          ]
diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl
index 5ac7347ed49..04475daccd2 100644
--- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl
+++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl
@@ -7370,6 +7370,8 @@ FSharp.Compiler.Syntax.SynField: FSharp.Compiler.Syntax.SynType fieldType
 FSharp.Compiler.Syntax.SynField: FSharp.Compiler.Syntax.SynType get_fieldType()
 FSharp.Compiler.Syntax.SynField: FSharp.Compiler.SyntaxTrivia.SynFieldTrivia get_trivia()
 FSharp.Compiler.Syntax.SynField: FSharp.Compiler.SyntaxTrivia.SynFieldTrivia trivia
+FSharp.Compiler.Syntax.SynField: FSharp.Compiler.Text.Range Range
+FSharp.Compiler.Syntax.SynField: FSharp.Compiler.Text.Range get_Range()
 FSharp.Compiler.Syntax.SynField: FSharp.Compiler.Text.Range get_range()
 FSharp.Compiler.Syntax.SynField: FSharp.Compiler.Text.Range range
 FSharp.Compiler.Syntax.SynField: FSharp.Compiler.Xml.PreXmlDoc get_xmlDoc()
@@ -9755,8 +9757,10 @@ FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: FSharp.Compiler.SyntaxTrivia.SynFie
 FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: FSharp.Compiler.SyntaxTrivia.SynFieldTrivia get_Zero()
 FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.SynLeadingKeyword] LeadingKeyword
 FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.SynLeadingKeyword] get_LeadingKeyword()
+FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] MutableKeyword
+FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_MutableKeyword()
 FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: System.String ToString()
-FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: Void .ctor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.SynLeadingKeyword])
+FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: Void .ctor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.SynLeadingKeyword], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range])
 FSharp.Compiler.SyntaxTrivia.SynLeadingKeyword+Abstract: FSharp.Compiler.Text.Range abstractRange
 FSharp.Compiler.SyntaxTrivia.SynLeadingKeyword+Abstract: FSharp.Compiler.Text.Range get_abstractRange()
 FSharp.Compiler.SyntaxTrivia.SynLeadingKeyword+AbstractMember: FSharp.Compiler.Text.Range abstractRange
diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl
index 6b17b4e36a4..dedad02e253 100644
--- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl
+++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl
@@ -7370,6 +7370,8 @@ FSharp.Compiler.Syntax.SynField: FSharp.Compiler.Syntax.SynType fieldType
 FSharp.Compiler.Syntax.SynField: FSharp.Compiler.Syntax.SynType get_fieldType()
 FSharp.Compiler.Syntax.SynField: FSharp.Compiler.SyntaxTrivia.SynFieldTrivia get_trivia()
 FSharp.Compiler.Syntax.SynField: FSharp.Compiler.SyntaxTrivia.SynFieldTrivia trivia
+FSharp.Compiler.Syntax.SynField: FSharp.Compiler.Text.Range Range
+FSharp.Compiler.Syntax.SynField: FSharp.Compiler.Text.Range get_Range()
 FSharp.Compiler.Syntax.SynField: FSharp.Compiler.Text.Range get_range()
 FSharp.Compiler.Syntax.SynField: FSharp.Compiler.Text.Range range
 FSharp.Compiler.Syntax.SynField: FSharp.Compiler.Xml.PreXmlDoc get_xmlDoc()
@@ -9755,8 +9757,10 @@ FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: FSharp.Compiler.SyntaxTrivia.SynFie
 FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: FSharp.Compiler.SyntaxTrivia.SynFieldTrivia get_Zero()
 FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.SynLeadingKeyword] LeadingKeyword
 FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.SynLeadingKeyword] get_LeadingKeyword()
+FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] MutableKeyword
+FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_MutableKeyword()
 FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: System.String ToString()
-FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: Void .ctor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.SynLeadingKeyword])
+FSharp.Compiler.SyntaxTrivia.SynFieldTrivia: Void .ctor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.SynLeadingKeyword], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range])
 FSharp.Compiler.SyntaxTrivia.SynLeadingKeyword+Abstract: FSharp.Compiler.Text.Range abstractRange
 FSharp.Compiler.SyntaxTrivia.SynLeadingKeyword+Abstract: FSharp.Compiler.Text.Range get_abstractRange()
 FSharp.Compiler.SyntaxTrivia.SynLeadingKeyword+AbstractMember: FSharp.Compiler.Text.Range abstractRange
diff --git a/tests/fsharp/typecheck/sigs/neg16.bsl b/tests/fsharp/typecheck/sigs/neg16.bsl
index fa193383e45..9cb22ec9c0a 100644
--- a/tests/fsharp/typecheck/sigs/neg16.bsl
+++ b/tests/fsharp/typecheck/sigs/neg16.bsl
@@ -81,7 +81,7 @@ neg16.fs(102,3,103,9): typecheck error FS0823: The 'VolatileField' attribute may
 
 neg16.fs(102,3,103,9): typecheck error FS0879: Volatile fields must be marked 'mutable' and cannot be thread-static
 
-neg16.fs(119,17,119,24): typecheck error FS0823: The 'VolatileField' attribute may only be used on 'let' bindings in classes
+neg16.fs(119,17,119,18): typecheck error FS0823: The 'VolatileField' attribute may only be used on 'let' bindings in classes
 
 neg16.fs(106,5,107,19): typecheck error FS0879: Volatile fields must be marked 'mutable' and cannot be thread-static
 
diff --git a/tests/fsharp/typecheck/sigs/neg28.bsl b/tests/fsharp/typecheck/sigs/neg28.bsl
index 1b428ae309e..3893eaf1fdd 100644
--- a/tests/fsharp/typecheck/sigs/neg28.bsl
+++ b/tests/fsharp/typecheck/sigs/neg28.bsl
@@ -1,7 +1,7 @@
 
 neg28.fsx(5,10,5,11): typecheck error FS1180: The struct, record or union type 'X' has the 'StructuralEquality' attribute but the component type '(int -> int)' does not satisfy the 'equality' constraint
 
-neg28.fsx(12,13,12,20): typecheck error FS0880: Uninitialized 'val' fields must be mutable and marked with the '[]' attribute. Consider using a 'let' binding instead of a 'val' field.
+neg28.fsx(12,13,12,14): typecheck error FS0880: Uninitialized 'val' fields must be mutable and marked with the '[]' attribute. Consider using a 'let' binding instead of a 'val' field.
 
 neg28.fsx(19,13,19,14): typecheck error FS1181: Each argument of the primary constructor for a struct must be given a type, for example 'type S(x1:int, x2: int) = ...'. These arguments determine the fields of the struct.
 
diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_Regressions02b.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_Regressions02b.fs
index 175823c0e39..eac9452c02c 100644
--- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_Regressions02b.fs
+++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_Regressions02b.fs
@@ -1,7 +1,7 @@
 // #Regression #Conformance #ObjectOrientedTypes #Structs 
 // Regression for 4643:
 // infinite loop in typechecker - caused by recursive struct check via self typed static field
-//Static 'val' fields in types must be mutable, private and marked with the '\[\]' attribute\. They are initialized to the 'null' or 'zero' value for their type\. Consider also using a 'static let mutable' binding in a class type\.$
+//Static 'val' fields in types must be mutable, private and marked with the '\[\]' attribute\. They are initialized to the 'null' or 'zero' value for their type\. Consider also using a 'static let mutable' binding in a class type\.$
 []
 type RIP(x:int) =
 
diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/E_emptyRecord.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/E_emptyRecord.fsx
index 847a5987b20..dfcd6a2e2a1 100644
--- a/tests/fsharpqa/Source/InteractiveSession/Misc/E_emptyRecord.fsx
+++ b/tests/fsharpqa/Source/InteractiveSession/Misc/E_emptyRecord.fsx
@@ -1,5 +1,5 @@
 // #Regression #NoMT #FSI 
 // Regression test for FSHARP1.0:5629
-//Unexpected symbol '}' in field declaration\. Expected identifier or other token\.$
+//Expecting record field
 type R = { };;
 exit 1;;
diff --git a/tests/service/XmlDocTests.fs b/tests/service/XmlDocTests.fs
index bdb4fd81444..0872f118db1 100644
--- a/tests/service/XmlDocTests.fs
+++ b/tests/service/XmlDocTests.fs
@@ -1334,7 +1334,7 @@ type Point =
     match parseResults.ParseTree with
     | Members([SynMemberDefn.ValField(fieldInfo = SynField(range = fieldRange); range = range)]) ->
         assertRange (4, 8) (8, 20) range
-        assertRange (8, 12) (8, 20) fieldRange
+        assertRange (4, 8) (8, 20) fieldRange
     | x ->
         failwith $"Unexpected ParsedInput %A{x}"
 
diff --git a/tests/service/data/SyntaxTree/Exception/Recover Function Type 01.fs.bsl b/tests/service/data/SyntaxTree/Exception/Recover Function Type 01.fs.bsl
index 9136c672d0f..690183a18b6 100644
--- a/tests/service/data/SyntaxTree/Exception/Recover Function Type 01.fs.bsl	
+++ b/tests/service/data/SyntaxTree/Exception/Recover Function Type 01.fs.bsl	
@@ -19,7 +19,8 @@ ImplFile
                                 (3,17--3,27), { ArrowRange = (3,21--3,23) }),
                              false,
                              PreXmlDoc ((3,17), FSharp.Compiler.Xml.XmlDocCollector),
-                             None, (3,17--3,27), { LeadingKeyword = None })],
+                             None, (3,17--3,27), { LeadingKeyword = None
+                                                   MutableKeyword = None })],
                        PreXmlDocEmpty, None, (3,10--3,27), { BarRange = None }),
                     None, PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
                     None, (3,0--3,27)), None, [], (3,0--3,27)), (3,0--3,27));
@@ -34,7 +35,8 @@ ImplFile
                             ([], false, None,
                              LongIdent (SynLongIdent ([int], [], [None])), false,
                              PreXmlDoc ((4,19), FSharp.Compiler.Xml.XmlDocCollector),
-                             None, (4,19--4,22), { LeadingKeyword = None })],
+                             None, (4,19--4,22), { LeadingKeyword = None
+                                                   MutableKeyword = None })],
                        PreXmlDocEmpty, None, (4,10--4,22), { BarRange = None }),
                     None, PreXmlDoc ((4,0), FSharp.Compiler.Xml.XmlDocCollector),
                     None, (4,0--4,22)), None, [], (4,0--4,22)), (4,0--4,22))],
diff --git a/tests/service/data/SyntaxTree/LeadingKeyword/StaticValKeyword.fsi.bsl b/tests/service/data/SyntaxTree/LeadingKeyword/StaticValKeyword.fsi.bsl
index 28e40121327..a30354d3b41 100644
--- a/tests/service/data/SyntaxTree/LeadingKeyword/StaticValKeyword.fsi.bsl
+++ b/tests/service/data/SyntaxTree/LeadingKeyword/StaticValKeyword.fsi.bsl
@@ -23,8 +23,9 @@ SigFile
                             PreXmlDoc ((5,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (5,4--5,29),
                             { LeadingKeyword =
-                               Some (StaticVal ((5,4--5,10), (5,11--5,14))) }),
-                         (5,4--5,29))], (5,4--5,29)), [], (4,5--5,29),
+                               Some (StaticVal ((5,4--5,10), (5,11--5,14)))
+                              MutableKeyword = None }), (5,4--5,29))],
+                     (5,4--5,29)), [], (4,5--5,29),
                   { LeadingKeyword = Type (4,0--4,4)
                     EqualsRange = Some (4,7--4,8)
                     WithKeyword = None })], (4,0--5,29))], PreXmlDocEmpty, [],
diff --git a/tests/service/data/SyntaxTree/LeadingKeyword/ValKeyword.fsi.bsl b/tests/service/data/SyntaxTree/LeadingKeyword/ValKeyword.fsi.bsl
index 9d3675ba2e3..1c940b8d6fd 100644
--- a/tests/service/data/SyntaxTree/LeadingKeyword/ValKeyword.fsi.bsl
+++ b/tests/service/data/SyntaxTree/LeadingKeyword/ValKeyword.fsi.bsl
@@ -18,8 +18,9 @@ SigFile
                             LongIdent (SynLongIdent ([int], [], [None])), false,
                             PreXmlDoc ((5,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (5,4--5,15),
-                            { LeadingKeyword = Some (Val (5,4--5,7)) }),
-                         (5,4--5,15))], (5,4--5,15)), [], (4,5--5,15),
+                            { LeadingKeyword = Some (Val (5,4--5,7))
+                              MutableKeyword = None }), (5,4--5,15))],
+                     (5,4--5,15)), [], (4,5--5,15),
                   { LeadingKeyword = Type (4,0--4,4)
                     EqualsRange = Some (4,7--4,8)
                     WithKeyword = None })], (4,0--5,15))], PreXmlDocEmpty, [],
diff --git a/tests/service/data/SyntaxTree/Member/Field 01.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 01.fs.bsl
index 19453574e0a..add8ac4adbe 100644
--- a/tests/service/data/SyntaxTree/Member/Field 01.fs.bsl	
+++ b/tests/service/data/SyntaxTree/Member/Field 01.fs.bsl	
@@ -16,9 +16,10 @@ ImplFile
                            ([], false, Some F1,
                             LongIdent (SynLongIdent ([int], [], [None])), false,
                             PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (4,8--4,15),
-                            { LeadingKeyword = Some (Val (4,4--4,7)) }),
-                         (4,4--4,15))], (4,4--4,15)), [], None, (3,5--4,15),
+                            None, (4,4--4,15),
+                            { LeadingKeyword = Some (Val (4,4--4,7))
+                              MutableKeyword = None }), (4,4--4,15))],
+                     (4,4--4,15)), [], None, (3,5--4,15),
                   { LeadingKeyword = Type (3,0--3,4)
                     EqualsRange = Some (3,7--3,8)
                     WithKeyword = None })], (3,0--4,15))],
diff --git a/tests/service/data/SyntaxTree/Member/Field 02.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 02.fs.bsl
index fff1abdc078..33eba0a9f87 100644
--- a/tests/service/data/SyntaxTree/Member/Field 02.fs.bsl	
+++ b/tests/service/data/SyntaxTree/Member/Field 02.fs.bsl	
@@ -16,17 +16,18 @@ ImplFile
                            ([], false, Some F1, FromParseError (4,11--4,11),
                             false,
                             PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (4,8--5,4),
-                            { LeadingKeyword = Some (Val (4,4--4,7)) }),
-                         (4,4--4,11));
+                            None, (4,4--4,11),
+                            { LeadingKeyword = Some (Val (4,4--4,7))
+                              MutableKeyword = None }), (4,4--4,11));
                       ValField
                         (SynField
                            ([], false, Some F2,
                             LongIdent (SynLongIdent ([int], [], [None])), false,
                             PreXmlDoc ((5,4), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (5,8--5,15),
-                            { LeadingKeyword = Some (Val (5,4--5,7)) }),
-                         (5,4--5,15))], (4,4--5,15)), [], None, (3,5--5,15),
+                            None, (5,4--5,15),
+                            { LeadingKeyword = Some (Val (5,4--5,7))
+                              MutableKeyword = None }), (5,4--5,15))],
+                     (4,4--5,15)), [], None, (3,5--5,15),
                   { LeadingKeyword = Type (3,0--3,4)
                     EqualsRange = Some (3,7--3,8)
                     WithKeyword = None })], (3,0--5,15));
diff --git a/tests/service/data/SyntaxTree/Member/Field 03.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 03.fs.bsl
index de49a40d0ab..4308cbcfebb 100644
--- a/tests/service/data/SyntaxTree/Member/Field 03.fs.bsl	
+++ b/tests/service/data/SyntaxTree/Member/Field 03.fs.bsl	
@@ -13,19 +13,21 @@ ImplFile
                     (Unspecified,
                      [ValField
                         (SynField
-                           ([], false, Some F1, FromParseError (5,4--5,4), false,
+                           ([], false, Some F1, FromParseError (4,10--4,10),
+                            false,
                             PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (4,8--134217728,0),
-                            { LeadingKeyword = Some (Val (4,4--4,7)) }),
-                         (4,4--5,4));
+                            None, (4,4--4,10),
+                            { LeadingKeyword = Some (Val (4,4--4,7))
+                              MutableKeyword = None }), (4,4--4,10));
                       ValField
                         (SynField
                            ([], false, Some F2,
                             LongIdent (SynLongIdent ([int], [], [None])), false,
                             PreXmlDoc ((5,4), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (5,8--5,15),
-                            { LeadingKeyword = Some (Val (5,4--5,7)) }),
-                         (5,4--5,15))], (4,4--5,15)), [], None, (3,5--5,15),
+                            None, (5,4--5,15),
+                            { LeadingKeyword = Some (Val (5,4--5,7))
+                              MutableKeyword = None }), (5,4--5,15))],
+                     (4,4--5,15)), [], None, (3,5--5,15),
                   { LeadingKeyword = Type (3,0--3,4)
                     EqualsRange = Some (3,7--3,8)
                     WithKeyword = None })], (3,0--5,15));
diff --git a/tests/service/data/SyntaxTree/Member/Field 04.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 04.fs.bsl
index 17a1c250067..e481768ccb4 100644
--- a/tests/service/data/SyntaxTree/Member/Field 04.fs.bsl	
+++ b/tests/service/data/SyntaxTree/Member/Field 04.fs.bsl	
@@ -13,22 +13,23 @@ ImplFile
                     (Unspecified,
                      [ValField
                         (SynField
-                           ([], false, Some , FromParseError (1,13--1,13), false,
+                           ([], false, None, FromParseError (4,7--4,7), false,
                             PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (4,8--134217728,0),
-                            { LeadingKeyword = Some (Val (4,4--4,7)) }),
-                         (1,13--4,7));
+                            None, (4,4--4,7),
+                            { LeadingKeyword = Some (Val (4,4--4,7))
+                              MutableKeyword = None }), (4,4--4,7));
                       ValField
                         (SynField
                            ([], false, Some F2,
                             LongIdent (SynLongIdent ([int], [], [None])), false,
                             PreXmlDoc ((5,4), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (5,8--5,15),
-                            { LeadingKeyword = Some (Val (5,4--5,7)) }),
-                         (5,4--5,15))], (1,13--5,15)), [], None, (1,13--5,15),
+                            None, (5,4--5,15),
+                            { LeadingKeyword = Some (Val (5,4--5,7))
+                              MutableKeyword = None }), (5,4--5,15))],
+                     (4,4--5,15)), [], None, (3,5--5,15),
                   { LeadingKeyword = Type (3,0--3,4)
                     EqualsRange = Some (3,7--3,8)
-                    WithKeyword = None })], (1,13--5,15));
+                    WithKeyword = None })], (3,0--5,15));
            Expr (Const (Unit, (7,0--7,2)), (7,0--7,2))],
           PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
           (1,0--7,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
diff --git a/tests/service/data/SyntaxTree/Member/Field 05.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 05.fs.bsl
index e5485cf278c..46cf2e29c7f 100644
--- a/tests/service/data/SyntaxTree/Member/Field 05.fs.bsl	
+++ b/tests/service/data/SyntaxTree/Member/Field 05.fs.bsl	
@@ -16,9 +16,10 @@ ImplFile
                            ([], false, Some F, FromParseError (4,10--4,10),
                             false,
                             PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (4,8--6,1),
-                            { LeadingKeyword = Some (Val (4,4--4,7)) }),
-                         (4,4--4,10))], (4,4--4,10)), [], None, (3,5--4,10),
+                            None, (4,4--4,10),
+                            { LeadingKeyword = Some (Val (4,4--4,7))
+                              MutableKeyword = None }), (4,4--4,10))],
+                     (4,4--4,10)), [], None, (3,5--4,10),
                   { LeadingKeyword = Type (3,0--3,4)
                     EqualsRange = Some (3,7--3,8)
                     WithKeyword = None })], (3,0--4,10));
diff --git a/tests/service/data/SyntaxTree/Member/Field 06.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 06.fs.bsl
index 066a055a8da..723a8c44f25 100644
--- a/tests/service/data/SyntaxTree/Member/Field 06.fs.bsl	
+++ b/tests/service/data/SyntaxTree/Member/Field 06.fs.bsl	
@@ -13,14 +13,14 @@ ImplFile
                     (Unspecified,
                      [ValField
                         (SynField
-                           ([], false, Some F, FromParseError (6,1--6,1), false,
+                           ([], false, Some F, FromParseError (4,9--4,9), false,
                             PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (4,8--134217728,0),
-                            { LeadingKeyword = Some (Val (4,4--4,7)) }),
-                         (4,4--6,1))], (4,4--6,1)), [], None, (3,5--6,1),
-                  { LeadingKeyword = Type (3,0--3,4)
-                    EqualsRange = Some (3,7--3,8)
-                    WithKeyword = None })], (3,0--6,1));
+                            None, (4,4--4,9),
+                            { LeadingKeyword = Some (Val (4,4--4,7))
+                              MutableKeyword = None }), (4,4--4,9))], (4,4--4,9)),
+                  [], None, (3,5--4,9), { LeadingKeyword = Type (3,0--3,4)
+                                          EqualsRange = Some (3,7--3,8)
+                                          WithKeyword = None })], (3,0--4,9));
            Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))],
           PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
           (1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
diff --git a/tests/service/data/SyntaxTree/Member/Field 07.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 07.fs.bsl
index f86322e7ed2..e62126034db 100644
--- a/tests/service/data/SyntaxTree/Member/Field 07.fs.bsl	
+++ b/tests/service/data/SyntaxTree/Member/Field 07.fs.bsl	
@@ -13,14 +13,14 @@ ImplFile
                     (Unspecified,
                      [ValField
                         (SynField
-                           ([], false, Some , FromParseError (1,13--1,13), false,
+                           ([], false, None, FromParseError (4,7--4,7), false,
                             PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (6,0--134217728,0),
-                            { LeadingKeyword = Some (Val (4,4--4,7)) }),
-                         (1,13--4,7))], (1,13--4,7)), [], None, (1,13--4,7),
-                  { LeadingKeyword = Type (3,0--3,4)
-                    EqualsRange = Some (3,7--3,8)
-                    WithKeyword = None })], (1,13--4,7));
+                            None, (4,4--4,7),
+                            { LeadingKeyword = Some (Val (4,4--4,7))
+                              MutableKeyword = None }), (4,4--4,7))], (4,4--4,7)),
+                  [], None, (3,5--4,7), { LeadingKeyword = Type (3,0--3,4)
+                                          EqualsRange = Some (3,7--3,8)
+                                          WithKeyword = None })], (3,0--4,7));
            Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))],
           PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
           (1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
diff --git a/tests/service/data/SyntaxTree/Member/Field 08.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 08.fs.bsl
index 000f2c63128..c74f09be72c 100644
--- a/tests/service/data/SyntaxTree/Member/Field 08.fs.bsl	
+++ b/tests/service/data/SyntaxTree/Member/Field 08.fs.bsl	
@@ -13,11 +13,12 @@ ImplFile
                     (Struct,
                      [ValField
                         (SynField
-                           ([], false, Some , FromParseError (1,13--1,13), false,
+                           ([], false, None, FromParseError (5,11--5,11), false,
                             PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (6,4--134217728,0),
-                            { LeadingKeyword = Some (Val (5,8--5,11)) }),
-                         (1,13--5,11))], (4,4--6,7)), [], None, (3,5--6,7),
+                            None, (5,8--5,11),
+                            { LeadingKeyword = Some (Val (5,8--5,11))
+                              MutableKeyword = None }), (5,8--5,11))],
+                     (4,4--6,7)), [], None, (3,5--6,7),
                   { LeadingKeyword = Type (3,0--3,4)
                     EqualsRange = Some (3,7--3,8)
                     WithKeyword = None })], (3,0--6,7));
diff --git a/tests/service/data/SyntaxTree/Member/Field 09.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 09.fs.bsl
index 22f89b87864..8b4d8d1fa48 100644
--- a/tests/service/data/SyntaxTree/Member/Field 09.fs.bsl	
+++ b/tests/service/data/SyntaxTree/Member/Field 09.fs.bsl	
@@ -13,15 +13,16 @@ ImplFile
                     (Unspecified,
                      [ValField
                         (SynField
-                           ([], true, Some , FromParseError (1,13--1,13), false,
+                           ([], true, None, FromParseError (4,14--4,14), false,
                             PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (6,0--134217728,0),
+                            None, (4,4--4,14),
                             { LeadingKeyword =
-                               Some (StaticVal ((4,4--4,10), (4,11--4,14))) }),
-                         (1,13--4,10))], (1,13--4,10)), [], None, (1,13--4,10),
+                               Some (StaticVal ((4,4--4,10), (4,11--4,14)))
+                              MutableKeyword = None }), (4,4--4,14))],
+                     (4,4--4,14)), [], None, (3,5--4,14),
                   { LeadingKeyword = Type (3,0--3,4)
                     EqualsRange = Some (3,7--3,8)
-                    WithKeyword = None })], (1,13--4,10));
+                    WithKeyword = None })], (3,0--4,14));
            Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))],
           PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
           (1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
diff --git a/tests/service/data/SyntaxTree/Member/Field 10.fs b/tests/service/data/SyntaxTree/Member/Field 10.fs
new file mode 100644
index 00000000000..4e4f23d2858
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Member/Field 10.fs	
@@ -0,0 +1,6 @@
+module Module
+
+type T =
+    static val mutable
+
+()
diff --git a/tests/service/data/SyntaxTree/Member/Field 10.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 10.fs.bsl
new file mode 100644
index 00000000000..77016903ad5
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Member/Field 10.fs.bsl	
@@ -0,0 +1,32 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Member/Field 10.fs", false, QualifiedNameOfFile Module, [], [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [T],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  ObjectModel
+                    (Unspecified,
+                     [ValField
+                        (SynField
+                           ([], true, None, FromParseError (4,22--4,22), true,
+                            PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (4,4--4,22),
+                            { LeadingKeyword =
+                               Some (StaticVal ((4,4--4,10), (4,11--4,14)))
+                              MutableKeyword = Some (4,15--4,22) }), (4,4--4,22))],
+                     (4,4--4,22)), [], None, (3,5--4,22),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--4,22));
+           Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(6,0)-(6,1) parse error Incomplete structured construct at or before this point in type definition. Expected identifier or other token.
diff --git a/tests/service/data/SyntaxTree/Member/Field 11.fs b/tests/service/data/SyntaxTree/Member/Field 11.fs
new file mode 100644
index 00000000000..5599e7906ae
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Member/Field 11.fs	
@@ -0,0 +1,6 @@
+module Module
+
+type T =
+    static val mutable private
+
+()
diff --git a/tests/service/data/SyntaxTree/Member/Field 11.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 11.fs.bsl
new file mode 100644
index 00000000000..4f3cfe4b8b4
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Member/Field 11.fs.bsl	
@@ -0,0 +1,32 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Member/Field 11.fs", false, QualifiedNameOfFile Module, [], [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [T],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  ObjectModel
+                    (Unspecified,
+                     [ValField
+                        (SynField
+                           ([], true, None, FromParseError (4,30--4,30), true,
+                            PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
+                            Some (Private (4,23--4,30)), (4,4--4,30),
+                            { LeadingKeyword =
+                               Some (StaticVal ((4,4--4,10), (4,11--4,14)))
+                              MutableKeyword = Some (4,15--4,22) }), (4,4--4,30))],
+                     (4,4--4,30)), [], None, (3,5--4,30),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--4,30));
+           Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(6,0)-(6,1) parse error Incomplete structured construct at or before this point in type definition. Expected identifier or other token.
diff --git a/tests/service/data/SyntaxTree/Member/Field 12.fs b/tests/service/data/SyntaxTree/Member/Field 12.fs
new file mode 100644
index 00000000000..0f62041753c
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Member/Field 12.fs	
@@ -0,0 +1,6 @@
+module Module
+
+type T =
+    static val mutable private F
+
+()
diff --git a/tests/service/data/SyntaxTree/Member/Field 12.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 12.fs.bsl
new file mode 100644
index 00000000000..d29045ba0e7
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Member/Field 12.fs.bsl	
@@ -0,0 +1,32 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Member/Field 12.fs", false, QualifiedNameOfFile Module, [], [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [T],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  ObjectModel
+                    (Unspecified,
+                     [ValField
+                        (SynField
+                           ([], true, Some F, FromParseError (4,32--4,32), true,
+                            PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
+                            Some (Private (4,23--4,30)), (4,4--4,32),
+                            { LeadingKeyword =
+                               Some (StaticVal ((4,4--4,10), (4,11--4,14)))
+                              MutableKeyword = Some (4,15--4,22) }), (4,4--4,32))],
+                     (4,4--4,32)), [], None, (3,5--4,32),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--4,32));
+           Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(6,0)-(6,1) parse error Incomplete structured construct at or before this point in type definition. Expected ':' or other token.
diff --git a/tests/service/data/SyntaxTree/Member/Field 13.fs b/tests/service/data/SyntaxTree/Member/Field 13.fs
new file mode 100644
index 00000000000..6656f609f9e
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Member/Field 13.fs	
@@ -0,0 +1,6 @@
+module Module
+
+type T =
+    static val mutable private F:
+
+()
diff --git a/tests/service/data/SyntaxTree/Member/Field 13.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 13.fs.bsl
new file mode 100644
index 00000000000..3b42126b6db
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Member/Field 13.fs.bsl	
@@ -0,0 +1,32 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Member/Field 13.fs", false, QualifiedNameOfFile Module, [], [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [T],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  ObjectModel
+                    (Unspecified,
+                     [ValField
+                        (SynField
+                           ([], true, Some F, FromParseError (4,33--4,33), true,
+                            PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
+                            Some (Private (4,23--4,30)), (4,4--4,33),
+                            { LeadingKeyword =
+                               Some (StaticVal ((4,4--4,10), (4,11--4,14)))
+                              MutableKeyword = Some (4,15--4,22) }), (4,4--4,33))],
+                     (4,4--4,33)), [], None, (3,5--4,33),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--4,33));
+           Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(6,0)-(6,1) parse error Incomplete structured construct at or before this point in type definition
diff --git a/tests/service/data/SyntaxTree/Member/Field 14.fs b/tests/service/data/SyntaxTree/Member/Field 14.fs
new file mode 100644
index 00000000000..fa2e7923047
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Member/Field 14.fs	
@@ -0,0 +1,6 @@
+module Module
+
+type T =
+    static val mutable private F: int
+
+()
diff --git a/tests/service/data/SyntaxTree/Member/Field 14.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 14.fs.bsl
new file mode 100644
index 00000000000..b9ae59996cf
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Member/Field 14.fs.bsl	
@@ -0,0 +1,31 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Member/Field 14.fs", false, QualifiedNameOfFile Module, [], [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [T],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  ObjectModel
+                    (Unspecified,
+                     [ValField
+                        (SynField
+                           ([], true, Some F,
+                            LongIdent (SynLongIdent ([int], [], [None])), true,
+                            PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
+                            Some (Private (4,23--4,30)), (4,4--4,37),
+                            { LeadingKeyword =
+                               Some (StaticVal ((4,4--4,10), (4,11--4,14)))
+                              MutableKeyword = Some (4,15--4,22) }), (4,4--4,37))],
+                     (4,4--4,37)), [], None, (3,5--4,37),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--4,37));
+           Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Member/Field 15.fs b/tests/service/data/SyntaxTree/Member/Field 15.fs
new file mode 100644
index 00000000000..77f72b83e97
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Member/Field 15.fs	
@@ -0,0 +1,7 @@
+module Module
+
+type T =
+    []
+    static val F: int
+
+()
diff --git a/tests/service/data/SyntaxTree/Member/Field 15.fs.bsl b/tests/service/data/SyntaxTree/Member/Field 15.fs.bsl
new file mode 100644
index 00000000000..472d5e0c2f9
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Member/Field 15.fs.bsl	
@@ -0,0 +1,37 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Member/Field 15.fs", false, QualifiedNameOfFile Module, [], [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [T],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  ObjectModel
+                    (Unspecified,
+                     [ValField
+                        (SynField
+                           ([{ Attributes =
+                                [{ TypeName = SynLongIdent ([A], [], [None])
+                                   ArgExpr = Const (Unit, (4,6--4,7))
+                                   Target = None
+                                   AppliesToGetterAndSetter = false
+                                   Range = (4,6--4,7) }]
+                               Range = (4,4--4,9) }], true, Some F,
+                            LongIdent (SynLongIdent ([int], [], [None])), false,
+                            PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (4,4--5,21),
+                            { LeadingKeyword =
+                               Some (StaticVal ((5,4--5,10), (5,11--5,14)))
+                              MutableKeyword = None }), (4,4--5,21))],
+                     (4,4--5,21)), [], None, (3,5--5,21),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--5,21));
+           Expr (Const (Unit, (7,0--7,2)), (7,0--7,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--7,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/ModuleOrNamespaceSig/GlobalNamespaceShouldStartAtNamespaceKeyword.fsi.bsl b/tests/service/data/SyntaxTree/ModuleOrNamespaceSig/GlobalNamespaceShouldStartAtNamespaceKeyword.fsi.bsl
index 587df130b0f..13f845e312a 100644
--- a/tests/service/data/SyntaxTree/ModuleOrNamespaceSig/GlobalNamespaceShouldStartAtNamespaceKeyword.fsi.bsl
+++ b/tests/service/data/SyntaxTree/ModuleOrNamespaceSig/GlobalNamespaceShouldStartAtNamespaceKeyword.fsi.bsl
@@ -21,13 +21,15 @@ SigFile
                                   LongIdent
                                     (SynLongIdent ([string], [], [None])), false,
                                   PreXmlDoc ((6,20), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (6,20--6,26), { LeadingKeyword = None });
+                                  None, (6,20--6,26), { LeadingKeyword = None
+                                                        MutableKeyword = None });
                                SynField
                                  ([], false, None,
                                   LongIdent (SynLongIdent ([int], [], [None])),
                                   false,
                                   PreXmlDoc ((6,29), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (6,29--6,32), { LeadingKeyword = None })],
+                                  None, (6,29--6,32), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((6,11), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (6,13--6,32), { BarRange = Some (6,11--6,12) })],
                         (6,11--6,32)), (6,11--6,32)), [], (6,5--6,32),
diff --git a/tests/service/data/SyntaxTree/ModuleOrNamespaceSig/RangeMemberReturnsRangeOfSynModuleOrNamespaceSig.fsi.bsl b/tests/service/data/SyntaxTree/ModuleOrNamespaceSig/RangeMemberReturnsRangeOfSynModuleOrNamespaceSig.fsi.bsl
index bf2904ff046..8a0f981091f 100644
--- a/tests/service/data/SyntaxTree/ModuleOrNamespaceSig/RangeMemberReturnsRangeOfSynModuleOrNamespaceSig.fsi.bsl
+++ b/tests/service/data/SyntaxTree/ModuleOrNamespaceSig/RangeMemberReturnsRangeOfSynModuleOrNamespaceSig.fsi.bsl
@@ -22,13 +22,15 @@ SigFile
                                   LongIdent
                                     (SynLongIdent ([string], [], [None])), false,
                                   PreXmlDoc ((4,20), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (4,20--4,26), { LeadingKeyword = None });
+                                  None, (4,20--4,26), { LeadingKeyword = None
+                                                        MutableKeyword = None });
                                SynField
                                  ([], false, None,
                                   LongIdent (SynLongIdent ([int], [], [None])),
                                   false,
                                   PreXmlDoc ((4,29), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (4,29--4,32), { LeadingKeyword = None })],
+                                  None, (4,29--4,32), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((4,11), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (4,13--4,32), { BarRange = Some (4,11--4,12) })],
                         (4,11--4,32)), (4,11--4,32)), [], (4,5--4,32),
diff --git a/tests/service/data/SyntaxTree/NestedModule/RangeOfNestedModuleInSignatureFileShouldEndAtTheLastSynModuleSigDecl.fsi.bsl b/tests/service/data/SyntaxTree/NestedModule/RangeOfNestedModuleInSignatureFileShouldEndAtTheLastSynModuleSigDecl.fsi.bsl
index c949211307e..b52c329f8c9 100644
--- a/tests/service/data/SyntaxTree/NestedModule/RangeOfNestedModuleInSignatureFileShouldEndAtTheLastSynModuleSigDecl.fsi.bsl
+++ b/tests/service/data/SyntaxTree/NestedModule/RangeOfNestedModuleInSignatureFileShouldEndAtTheLastSynModuleSigDecl.fsi.bsl
@@ -297,7 +297,8 @@ SigFile
                                          (31,22--31,25)), false,
                                       PreXmlDoc ((31,22), FSharp.Compiler.Xml.XmlDocCollector),
                                       None, (31,22--31,25),
-                                      { LeadingKeyword = None })],
+                                      { LeadingKeyword = None
+                                        MutableKeyword = None })],
                                 PreXmlDoc ((31,6), FSharp.Compiler.Xml.XmlDocCollector),
                                 None, (30,6--31,25),
                                 { BarRange = Some (31,6--31,7) });
@@ -311,7 +312,8 @@ SigFile
                                          (33,22--33,25)), false,
                                       PreXmlDoc ((33,22), FSharp.Compiler.Xml.XmlDocCollector),
                                       None, (33,22--33,25),
-                                      { LeadingKeyword = None })],
+                                      { LeadingKeyword = None
+                                        MutableKeyword = None })],
                                 PreXmlDoc ((33,6), FSharp.Compiler.Xml.XmlDocCollector),
                                 None, (32,6--33,25),
                                 { BarRange = Some (33,6--33,7) });
@@ -325,7 +327,8 @@ SigFile
                                          (35,22--35,25)), false,
                                       PreXmlDoc ((35,22), FSharp.Compiler.Xml.XmlDocCollector),
                                       None, (35,22--35,25),
-                                      { LeadingKeyword = None })],
+                                      { LeadingKeyword = None
+                                        MutableKeyword = None })],
                                 PreXmlDoc ((35,6), FSharp.Compiler.Xml.XmlDocCollector),
                                 None, (34,6--35,25),
                                 { BarRange = Some (35,6--35,7) });
@@ -339,7 +342,8 @@ SigFile
                                          (37,22--37,25)), false,
                                       PreXmlDoc ((37,22), FSharp.Compiler.Xml.XmlDocCollector),
                                       None, (37,22--37,25),
-                                      { LeadingKeyword = None })],
+                                      { LeadingKeyword = None
+                                        MutableKeyword = None })],
                                 PreXmlDoc ((37,6), FSharp.Compiler.Xml.XmlDocCollector),
                                 None, (36,6--37,25),
                                 { BarRange = Some (37,6--37,7) });
@@ -353,7 +357,8 @@ SigFile
                                          (39,22--39,25)), false,
                                       PreXmlDoc ((39,22), FSharp.Compiler.Xml.XmlDocCollector),
                                       None, (39,22--39,25),
-                                      { LeadingKeyword = None })],
+                                      { LeadingKeyword = None
+                                        MutableKeyword = None })],
                                 PreXmlDoc ((39,6), FSharp.Compiler.Xml.XmlDocCollector),
                                 None, (38,6--39,25),
                                 { BarRange = Some (39,6--39,7) });
@@ -367,7 +372,8 @@ SigFile
                                          (41,22--41,25)), false,
                                       PreXmlDoc ((41,22), FSharp.Compiler.Xml.XmlDocCollector),
                                       None, (41,22--41,25),
-                                      { LeadingKeyword = None })],
+                                      { LeadingKeyword = None
+                                        MutableKeyword = None })],
                                 PreXmlDoc ((41,6), FSharp.Compiler.Xml.XmlDocCollector),
                                 None, (40,6--41,25),
                                 { BarRange = Some (41,6--41,7) })],
diff --git a/tests/service/data/SyntaxTree/SignatureType/RangeOfAttributeShouldBeIncludedInSynExceptionDefnReprAndSynExceptionSig.fsi.bsl b/tests/service/data/SyntaxTree/SignatureType/RangeOfAttributeShouldBeIncludedInSynExceptionDefnReprAndSynExceptionSig.fsi.bsl
index 35f55a52373..e92edcc8113 100644
--- a/tests/service/data/SyntaxTree/SignatureType/RangeOfAttributeShouldBeIncludedInSynExceptionDefnReprAndSynExceptionSig.fsi.bsl
+++ b/tests/service/data/SyntaxTree/SignatureType/RangeOfAttributeShouldBeIncludedInSynExceptionDefnReprAndSynExceptionSig.fsi.bsl
@@ -26,13 +26,15 @@ SigFile
                             ([], false, None,
                              LongIdent (SynLongIdent ([obj], [], [None])), false,
                              PreXmlDoc ((6,25), FSharp.Compiler.Xml.XmlDocCollector),
-                             None, (6,25--6,28), { LeadingKeyword = None });
+                             None, (6,25--6,28), { LeadingKeyword = None
+                                                   MutableKeyword = None });
                           SynField
                             ([], false, Some range,
                              LongIdent (SynLongIdent ([range], [], [None])),
                              false,
                              PreXmlDoc ((6,31), FSharp.Compiler.Xml.XmlDocCollector),
-                             None, (6,31--6,43), { LeadingKeyword = None })],
+                             None, (6,31--6,43), { LeadingKeyword = None
+                                                   MutableKeyword = None })],
                        PreXmlDocEmpty, None, (6,10--6,43), { BarRange = None }),
                     None, PreXmlDoc ((5,0), FSharp.Compiler.Xml.XmlDocCollector),
                     None, (5,0--6,43)), None, [], (5,0--6,43)), (5,0--6,43))],
diff --git a/tests/service/data/SyntaxTree/SignatureType/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fsi.bsl b/tests/service/data/SyntaxTree/SignatureType/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fsi.bsl
index 1046fa25479..bf3950ebf3c 100644
--- a/tests/service/data/SyntaxTree/SignatureType/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fsi.bsl
+++ b/tests/service/data/SyntaxTree/SignatureType/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fsi.bsl
@@ -41,7 +41,8 @@ SigFile
                            ([], false, Some LongNameBarBarBarBarBarBarBar,
                             LongIdent (SynLongIdent ([int], [], [None])), false,
                             PreXmlDoc ((10,12), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (10,12--10,46), { LeadingKeyword = None })],
+                            None, (10,12--10,46), { LeadingKeyword = None
+                                                    MutableKeyword = None })],
                         (8,4--11,9)), (8,4--11,9)),
                   [Member
                      (SynValSig
diff --git a/tests/service/data/SyntaxTree/SignatureType/RangeOfMembersShouldBeIncludedInSynExceptionSigAndSynModuleSigDeclException.fsi.bsl b/tests/service/data/SyntaxTree/SignatureType/RangeOfMembersShouldBeIncludedInSynExceptionSigAndSynModuleSigDeclException.fsi.bsl
index 27d724e66ab..8a7477a0400 100644
--- a/tests/service/data/SyntaxTree/SignatureType/RangeOfMembersShouldBeIncludedInSynExceptionSigAndSynModuleSigDeclException.fsi.bsl
+++ b/tests/service/data/SyntaxTree/SignatureType/RangeOfMembersShouldBeIncludedInSynExceptionSigAndSynModuleSigDeclException.fsi.bsl
@@ -15,13 +15,15 @@ SigFile
                             ([], false, None,
                              LongIdent (SynLongIdent ([obj], [], [None])), false,
                              PreXmlDoc ((4,25), FSharp.Compiler.Xml.XmlDocCollector),
-                             None, (4,25--4,28), { LeadingKeyword = None });
+                             None, (4,25--4,28), { LeadingKeyword = None
+                                                   MutableKeyword = None });
                           SynField
                             ([], false, Some range,
                              LongIdent (SynLongIdent ([range], [], [None])),
                              false,
                              PreXmlDoc ((4,31), FSharp.Compiler.Xml.XmlDocCollector),
-                             None, (4,31--4,43), { LeadingKeyword = None })],
+                             None, (4,31--4,43), { LeadingKeyword = None
+                                                   MutableKeyword = None })],
                        PreXmlDocEmpty, None, (4,10--4,43), { BarRange = None }),
                     None, PreXmlDoc ((4,0), FSharp.Compiler.Xml.XmlDocCollector),
                     None, (4,0--4,43)), Some (4,44--4,48),
diff --git a/tests/service/data/SyntaxTree/SignatureType/RangeOfSynTypeDefnSigRecordShouldEndAtLastMember.fsi.bsl b/tests/service/data/SyntaxTree/SignatureType/RangeOfSynTypeDefnSigRecordShouldEndAtLastMember.fsi.bsl
index 5aa63f103b5..d0fe920321f 100644
--- a/tests/service/data/SyntaxTree/SignatureType/RangeOfSynTypeDefnSigRecordShouldEndAtLastMember.fsi.bsl
+++ b/tests/service/data/SyntaxTree/SignatureType/RangeOfSynTypeDefnSigRecordShouldEndAtLastMember.fsi.bsl
@@ -18,7 +18,8 @@ SigFile
                            ([], false, Some Level,
                             LongIdent (SynLongIdent ([int], [], [None])), false,
                             PreXmlDoc ((4,6), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (4,6--4,16), { LeadingKeyword = None })],
+                            None, (4,6--4,16), { LeadingKeyword = None
+                                                 MutableKeyword = None })],
                         (4,4--4,18)), (4,4--4,18)),
                   [Member
                      (SynValSig
diff --git a/tests/service/data/SyntaxTree/SignatureType/RangeOfSynTypeDefnSigSimpleShouldEndAtLastVal.fsi.bsl b/tests/service/data/SyntaxTree/SignatureType/RangeOfSynTypeDefnSigSimpleShouldEndAtLastVal.fsi.bsl
index df1725af6c4..7829833143a 100644
--- a/tests/service/data/SyntaxTree/SignatureType/RangeOfSynTypeDefnSigSimpleShouldEndAtLastVal.fsi.bsl
+++ b/tests/service/data/SyntaxTree/SignatureType/RangeOfSynTypeDefnSigSimpleShouldEndAtLastVal.fsi.bsl
@@ -17,8 +17,8 @@ SigFile
                          LongIdent (SynLongIdent ([int], [], [None])), false,
                          PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
                          None, (4,4--4,23),
-                         { LeadingKeyword = Some (Val (4,4--4,7)) }),
-                      (4,4--4,23));
+                         { LeadingKeyword = Some (Val (4,4--4,7))
+                           MutableKeyword = None }), (4,4--4,23));
                    ValField
                      (SynField
                         ([], false, Some SomeThingElse,
@@ -28,8 +28,8 @@ SigFile
                             (5,24--5,37), { ArrowRange = (5,28--5,30) }), false,
                          PreXmlDoc ((5,4), FSharp.Compiler.Xml.XmlDocCollector),
                          None, (5,4--5,37),
-                         { LeadingKeyword = Some (Val (5,4--5,7)) }),
-                      (5,4--5,37))], (3,5--5,37),
+                         { LeadingKeyword = Some (Val (5,4--5,7))
+                           MutableKeyword = None }), (5,4--5,37))], (3,5--5,37),
                   { LeadingKeyword = Type (3,0--3,4)
                     EqualsRange = None
                     WithKeyword = Some (3,20--3,24) })], (3,0--5,37))],
diff --git a/tests/service/data/SyntaxTree/SignatureType/SynTypeDefnSigWithUnionContainsTheRangeOfTheEqualsSign.fsi.bsl b/tests/service/data/SyntaxTree/SignatureType/SynTypeDefnSigWithUnionContainsTheRangeOfTheEqualsSign.fsi.bsl
index 54ca9aa3877..bfc76db57f5 100644
--- a/tests/service/data/SyntaxTree/SignatureType/SynTypeDefnSigWithUnionContainsTheRangeOfTheEqualsSign.fsi.bsl
+++ b/tests/service/data/SyntaxTree/SignatureType/SynTypeDefnSigWithUnionContainsTheRangeOfTheEqualsSign.fsi.bsl
@@ -22,7 +22,8 @@ SigFile
                                   LongIdent (SynLongIdent ([int], [], [None])),
                                   false,
                                   PreXmlDoc ((5,12), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (5,12--5,15), { LeadingKeyword = None })],
+                                  None, (5,12--5,15), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((5,0), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (5,2--5,15), { BarRange = Some (5,0--5,1) });
                          SynUnionCase
@@ -33,13 +34,15 @@ SigFile
                                   LongIdent (SynLongIdent ([int], [], [None])),
                                   false,
                                   PreXmlDoc ((6,15), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (6,15--6,18), { LeadingKeyword = None });
+                                  None, (6,15--6,18), { LeadingKeyword = None
+                                                        MutableKeyword = None });
                                SynField
                                  ([], false, None,
                                   LongIdent (SynLongIdent ([int], [], [None])),
                                   false,
                                   PreXmlDoc ((6,21), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (6,21--6,24), { LeadingKeyword = None })],
+                                  None, (6,21--6,24), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((6,0), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (6,2--6,24), { BarRange = Some (6,0--6,1) })],
                         (5,0--6,24)), (5,0--6,24)), [], (4,5--6,24),
diff --git a/tests/service/data/SyntaxTree/Type/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fs.bsl b/tests/service/data/SyntaxTree/Type/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fs.bsl
index 8ae96be677d..0b685986fc4 100644
--- a/tests/service/data/SyntaxTree/Type/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fs.bsl
+++ b/tests/service/data/SyntaxTree/Type/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fs.bsl
@@ -51,7 +51,8 @@ ImplFile
                                      [(4,34--4,35)], Some (4,38--4,39), false,
                                      (4,15--4,39)), false,
                                   PreXmlDoc ((4,15), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (4,15--4,39), { LeadingKeyword = None })],
+                                  None, (4,15--4,39), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (4,6--4,39), { BarRange = Some (4,4--4,5) })],
                         (4,4--4,39)), (4,4--4,39)), [], None, (2,0--4,39),
@@ -91,7 +92,8 @@ ImplFile
                            ([], false, Some Hash,
                             LongIdent (SynLongIdent ([int], [], [None])), false,
                             PreXmlDoc ((8,8), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (8,8--8,18), { LeadingKeyword = None });
+                            None, (8,8--8,18), { LeadingKeyword = None
+                                                 MutableKeyword = None });
                          SynField
                            ([], false, Some Foo,
                             App
@@ -102,7 +104,8 @@ ImplFile
                                [(9,20--9,21)], Some (9,24--9,25), false,
                                (9,14--9,25)), false,
                             PreXmlDoc ((9,8), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (9,8--9,25), { LeadingKeyword = None })],
+                            None, (9,8--9,25), { LeadingKeyword = None
+                                                 MutableKeyword = None })],
                         (7,4--10,5)), (7,4--10,5)), [], None, (6,4--10,5),
                   { LeadingKeyword = And (6,0--6,3)
                     EqualsRange = Some (6,56--6,57)
diff --git a/tests/service/data/SyntaxTree/Type/Record - Access 01.fs b/tests/service/data/SyntaxTree/Type/Record - Access 01.fs
new file mode 100644
index 00000000000..5aa6084b5f1
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Access 01.fs	
@@ -0,0 +1,8 @@
+module Module
+
+type R =
+    {
+        internal
+    }
+
+()
diff --git a/tests/service/data/SyntaxTree/Type/Record - Access 01.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Access 01.fs.bsl
new file mode 100644
index 00000000000..95895538080
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Access 01.fs.bsl	
@@ -0,0 +1,32 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Type/Record - Access 01.fs", false, QualifiedNameOfFile Module, [],
+      [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [R],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  Simple
+                    (Record
+                       (None,
+                        [SynField
+                           ([], false, None, FromParseError (5,16--5,16), false,
+                            PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (5,8--5,16), { LeadingKeyword = None
+                                                 MutableKeyword = None })],
+                        (4,4--6,5)), (4,4--6,5)), [], None, (3,5--6,5),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--6,5));
+           Expr (Const (Unit, (8,0--8,2)), (8,0--8,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--8,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(6,4)-(6,5) parse error Unexpected symbol '}' in field declaration. Expected identifier or other token.
+(5,8)-(6,5) parse error Accessibility modifiers are not permitted on record fields. Use 'type R = internal ...' or 'type R = private ...' to give an accessibility to the whole representation.
diff --git a/tests/service/data/SyntaxTree/Type/Record - Access 02.fs b/tests/service/data/SyntaxTree/Type/Record - Access 02.fs
new file mode 100644
index 00000000000..0763672605a
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Access 02.fs	
@@ -0,0 +1,8 @@
+module Module
+
+type R =
+    {
+        mutable internal
+    }
+
+()
diff --git a/tests/service/data/SyntaxTree/Type/Record - Access 02.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Access 02.fs.bsl
new file mode 100644
index 00000000000..dac1c3f6255
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Access 02.fs.bsl	
@@ -0,0 +1,33 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Type/Record - Access 02.fs", false, QualifiedNameOfFile Module, [],
+      [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [R],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  Simple
+                    (Record
+                       (None,
+                        [SynField
+                           ([], false, None, FromParseError (5,24--5,24), true,
+                            PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (5,8--5,24),
+                            { LeadingKeyword = None
+                              MutableKeyword = Some (5,8--5,15) })], (4,4--6,5)),
+                     (4,4--6,5)), [], None, (3,5--6,5),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--6,5));
+           Expr (Const (Unit, (8,0--8,2)), (8,0--8,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--8,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(6,4)-(6,5) parse error Unexpected symbol '}' in field declaration. Expected identifier or other token.
+(5,8)-(6,5) parse error Accessibility modifiers are not permitted on record fields. Use 'type R = internal ...' or 'type R = private ...' to give an accessibility to the whole representation.
diff --git a/tests/service/data/SyntaxTree/Type/Record - Access 03.fs b/tests/service/data/SyntaxTree/Type/Record - Access 03.fs
new file mode 100644
index 00000000000..f2aeb291f6d
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Access 03.fs	
@@ -0,0 +1,8 @@
+module Module
+
+type R =
+    {
+        mutable internal F: int
+    }
+
+()
diff --git a/tests/service/data/SyntaxTree/Type/Record - Access 03.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Access 03.fs.bsl
new file mode 100644
index 00000000000..f819d61d7c4
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Access 03.fs.bsl	
@@ -0,0 +1,33 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Type/Record - Access 03.fs", false, QualifiedNameOfFile Module, [],
+      [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [R],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  Simple
+                    (Record
+                       (None,
+                        [SynField
+                           ([], false, Some F,
+                            LongIdent (SynLongIdent ([int], [], [None])), true,
+                            PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (5,8--5,31),
+                            { LeadingKeyword = None
+                              MutableKeyword = Some (5,8--5,15) })], (4,4--6,5)),
+                     (4,4--6,5)), [], None, (3,5--6,5),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--6,5));
+           Expr (Const (Unit, (8,0--8,2)), (8,0--8,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--8,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(5,8)-(5,31) parse error Accessibility modifiers are not permitted on record fields. Use 'type R = internal ...' or 'type R = private ...' to give an accessibility to the whole representation.
diff --git a/tests/service/data/SyntaxTree/Type/Record - Access 04.fs b/tests/service/data/SyntaxTree/Type/Record - Access 04.fs
new file mode 100644
index 00000000000..da377bf20b1
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Access 04.fs	
@@ -0,0 +1,8 @@
+module Module
+
+type R =
+    {
+        internal F: int
+    }
+
+()
diff --git a/tests/service/data/SyntaxTree/Type/Record - Access 04.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Access 04.fs.bsl
new file mode 100644
index 00000000000..1bcbe107b49
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Access 04.fs.bsl	
@@ -0,0 +1,32 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Type/Record - Access 04.fs", false, QualifiedNameOfFile Module, [],
+      [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [R],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  Simple
+                    (Record
+                       (None,
+                        [SynField
+                           ([], false, Some F,
+                            LongIdent (SynLongIdent ([int], [], [None])), false,
+                            PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (5,8--5,23), { LeadingKeyword = None
+                                                 MutableKeyword = None })],
+                        (4,4--6,5)), (4,4--6,5)), [], None, (3,5--6,5),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--6,5));
+           Expr (Const (Unit, (8,0--8,2)), (8,0--8,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--8,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(5,8)-(5,23) parse error Accessibility modifiers are not permitted on record fields. Use 'type R = internal ...' or 'type R = private ...' to give an accessibility to the whole representation.
diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 01.fs b/tests/service/data/SyntaxTree/Type/Record - Mutable 01.fs
new file mode 100644
index 00000000000..0aff5f6999d
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 01.fs	
@@ -0,0 +1,8 @@
+module Module
+
+type R =
+    {
+        mutable
+    }
+
+()
diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 01.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Mutable 01.fs.bsl
new file mode 100644
index 00000000000..1b629ceaf6f
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 01.fs.bsl	
@@ -0,0 +1,32 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Type/Record - Mutable 01.fs", false, QualifiedNameOfFile Module, [],
+      [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [R],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  Simple
+                    (Record
+                       (None,
+                        [SynField
+                           ([], false, None, FromParseError (5,15--5,15), true,
+                            PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (5,8--5,15),
+                            { LeadingKeyword = None
+                              MutableKeyword = Some (5,8--5,15) })], (4,4--6,5)),
+                     (4,4--6,5)), [], None, (3,5--6,5),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--6,5));
+           Expr (Const (Unit, (8,0--8,2)), (8,0--8,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--8,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(6,4)-(6,5) parse error Unexpected symbol '}' in field declaration. Expected identifier or other token.
diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 02.fs b/tests/service/data/SyntaxTree/Type/Record - Mutable 02.fs
new file mode 100644
index 00000000000..db2a7fa0f00
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 02.fs	
@@ -0,0 +1,9 @@
+module Module
+
+type R =
+    {
+        F1: int
+        mutable
+    }
+
+()
diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 02.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Mutable 02.fs.bsl
new file mode 100644
index 00000000000..6d7a08f3caa
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 02.fs.bsl	
@@ -0,0 +1,38 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Type/Record - Mutable 02.fs", false, QualifiedNameOfFile Module, [],
+      [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [R],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  Simple
+                    (Record
+                       (None,
+                        [SynField
+                           ([], false, Some F1,
+                            LongIdent (SynLongIdent ([int], [], [None])), false,
+                            PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (5,8--5,15), { LeadingKeyword = None
+                                                 MutableKeyword = None });
+                         SynField
+                           ([], false, None, FromParseError (6,15--6,15), true,
+                            PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (6,8--6,15),
+                            { LeadingKeyword = None
+                              MutableKeyword = Some (6,8--6,15) })], (4,4--7,5)),
+                     (4,4--7,5)), [], None, (3,5--7,5),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--7,5));
+           Expr (Const (Unit, (9,0--9,2)), (9,0--9,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--9,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(7,4)-(7,5) parse error Unexpected symbol '}' in field declaration. Expected identifier or other token.
diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 03.fs b/tests/service/data/SyntaxTree/Type/Record - Mutable 03.fs
new file mode 100644
index 00000000000..1f1c5dcbf47
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 03.fs	
@@ -0,0 +1,9 @@
+module Module
+
+type R =
+    {
+        mutable
+        F2: int
+    }
+
+()
diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 03.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Mutable 03.fs.bsl
new file mode 100644
index 00000000000..34b8bfe0d51
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 03.fs.bsl	
@@ -0,0 +1,38 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Type/Record - Mutable 03.fs", false, QualifiedNameOfFile Module, [],
+      [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [R],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  Simple
+                    (Record
+                       (None,
+                        [SynField
+                           ([], false, None, FromParseError (5,15--5,15), true,
+                            PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (5,8--5,15),
+                            { LeadingKeyword = None
+                              MutableKeyword = Some (5,8--5,15) });
+                         SynField
+                           ([], false, Some F2,
+                            LongIdent (SynLongIdent ([int], [], [None])), false,
+                            PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (6,8--6,15), { LeadingKeyword = None
+                                                 MutableKeyword = None })],
+                        (4,4--7,5)), (4,4--7,5)), [], None, (3,5--7,5),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--7,5));
+           Expr (Const (Unit, (9,0--9,2)), (9,0--9,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--9,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(5,16)-(6,8) parse error Incomplete structured construct at or before this point in field declaration. Expected identifier or other token.
diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 04.fs b/tests/service/data/SyntaxTree/Type/Record - Mutable 04.fs
new file mode 100644
index 00000000000..f61e93105ab
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 04.fs	
@@ -0,0 +1,10 @@
+module Module
+
+type R =
+    {
+        F1: int
+        mutable
+        F3: int
+    }
+
+()
diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 04.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Mutable 04.fs.bsl
new file mode 100644
index 00000000000..e8067343cd8
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 04.fs.bsl	
@@ -0,0 +1,44 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Type/Record - Mutable 04.fs", false, QualifiedNameOfFile Module, [],
+      [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [R],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  Simple
+                    (Record
+                       (None,
+                        [SynField
+                           ([], false, Some F1,
+                            LongIdent (SynLongIdent ([int], [], [None])), false,
+                            PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (5,8--5,15), { LeadingKeyword = None
+                                                 MutableKeyword = None });
+                         SynField
+                           ([], false, None, FromParseError (6,15--6,15), true,
+                            PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (6,8--6,15),
+                            { LeadingKeyword = None
+                              MutableKeyword = Some (6,8--6,15) });
+                         SynField
+                           ([], false, Some F3,
+                            LongIdent (SynLongIdent ([int], [], [None])), false,
+                            PreXmlDoc ((7,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (7,8--7,15), { LeadingKeyword = None
+                                                 MutableKeyword = None })],
+                        (4,4--8,5)), (4,4--8,5)), [], None, (3,5--8,5),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--8,5));
+           Expr (Const (Unit, (10,0--10,2)), (10,0--10,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--10,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(6,16)-(7,8) parse error Incomplete structured construct at or before this point in field declaration. Expected identifier or other token.
diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 05.fs b/tests/service/data/SyntaxTree/Type/Record - Mutable 05.fs
new file mode 100644
index 00000000000..81e33d6c9a8
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 05.fs	
@@ -0,0 +1,10 @@
+module Module
+
+type R =
+    {
+        F1: int
+        mutable F2: int
+        F3: int
+    }
+
+()
diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 05.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Mutable 05.fs.bsl
new file mode 100644
index 00000000000..3679671665f
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 05.fs.bsl	
@@ -0,0 +1,43 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Type/Record - Mutable 05.fs", false, QualifiedNameOfFile Module, [],
+      [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [R],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  Simple
+                    (Record
+                       (None,
+                        [SynField
+                           ([], false, Some F1,
+                            LongIdent (SynLongIdent ([int], [], [None])), false,
+                            PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (5,8--5,15), { LeadingKeyword = None
+                                                 MutableKeyword = None });
+                         SynField
+                           ([], false, Some F2,
+                            LongIdent (SynLongIdent ([int], [], [None])), true,
+                            PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (6,8--6,23),
+                            { LeadingKeyword = None
+                              MutableKeyword = Some (6,8--6,15) });
+                         SynField
+                           ([], false, Some F3,
+                            LongIdent (SynLongIdent ([int], [], [None])), false,
+                            PreXmlDoc ((7,8), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (7,8--7,15), { LeadingKeyword = None
+                                                 MutableKeyword = None })],
+                        (4,4--8,5)), (4,4--8,5)), [], None, (3,5--8,5),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--8,5));
+           Expr (Const (Unit, (10,0--10,2)), (10,0--10,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--10,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Type/Record 01.fs.bsl b/tests/service/data/SyntaxTree/Type/Record 01.fs.bsl
index 91d5f58ca56..1eabb2b2f62 100644
--- a/tests/service/data/SyntaxTree/Type/Record 01.fs.bsl	
+++ b/tests/service/data/SyntaxTree/Type/Record 01.fs.bsl	
@@ -16,11 +16,13 @@ ImplFile
                            ([], false, Some Invest,
                             LongIdent (SynLongIdent ([int], [], [None])), false,
                             PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (5,8--5,19), { LeadingKeyword = None });
+                            None, (5,8--5,19), { LeadingKeyword = None
+                                                 MutableKeyword = None });
                          SynField
                            ([], false, Some T, FromParseError (6,9--6,9), false,
                             PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (6,8--7,5), { LeadingKeyword = None })],
+                            None, (6,8--6,9), { LeadingKeyword = None
+                                                MutableKeyword = None })],
                         (4,4--7,5)), (4,4--7,5)), [], None, (3,5--7,5),
                   { LeadingKeyword = Type (3,0--3,4)
                     EqualsRange = Some (3,8--3,9)
diff --git a/tests/service/data/SyntaxTree/Type/Record 02.fs.bsl b/tests/service/data/SyntaxTree/Type/Record 02.fs.bsl
index 3ebdfe18ae4..11cabe541de 100644
--- a/tests/service/data/SyntaxTree/Type/Record 02.fs.bsl	
+++ b/tests/service/data/SyntaxTree/Type/Record 02.fs.bsl	
@@ -16,12 +16,14 @@ ImplFile
                            ([], false, Some Invest,
                             LongIdent (SynLongIdent ([int], [], [None])), false,
                             PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (5,8--5,19), { LeadingKeyword = None });
+                            None, (5,8--5,19), { LeadingKeyword = None
+                                                 MutableKeyword = None });
                          SynField
                            ([], false, Some T, FromParseError (6,11--6,11),
                             false,
                             PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (6,8--7,5), { LeadingKeyword = None })],
+                            None, (6,8--6,11), { LeadingKeyword = None
+                                                 MutableKeyword = None })],
                         (4,4--7,5)), (4,4--7,5)), [], None, (3,5--7,5),
                   { LeadingKeyword = Type (3,0--3,4)
                     EqualsRange = Some (3,8--3,9)
diff --git a/tests/service/data/SyntaxTree/Type/Record 03.fs b/tests/service/data/SyntaxTree/Type/Record 03.fs
new file mode 100644
index 00000000000..3bd731d5d69
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record 03.fs	
@@ -0,0 +1,6 @@
+module Module
+
+type R =
+    { }
+
+()
diff --git a/tests/service/data/SyntaxTree/Type/Record 03.fs.bsl b/tests/service/data/SyntaxTree/Type/Record 03.fs.bsl
new file mode 100644
index 00000000000..8777aa1b200
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record 03.fs.bsl	
@@ -0,0 +1,22 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Type/Record 03.fs", false, QualifiedNameOfFile Module, [], [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [R],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  Simple (Record (None, [], (4,4--4,7)), (4,4--4,7)), [], None,
+                  (3,5--4,7), { LeadingKeyword = Type (3,0--3,4)
+                                EqualsRange = Some (3,7--3,8)
+                                WithKeyword = None })], (3,0--4,7));
+           Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(4,6)-(4,7) parse error Expecting record field
diff --git a/tests/service/data/SyntaxTree/Type/Record 04.fs b/tests/service/data/SyntaxTree/Type/Record 04.fs
new file mode 100644
index 00000000000..f3437a91250
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record 04.fs	
@@ -0,0 +1,8 @@
+module Module
+
+type R =
+    {
+      ;
+    }
+
+()
diff --git a/tests/service/data/SyntaxTree/Type/Record 04.fs.bsl b/tests/service/data/SyntaxTree/Type/Record 04.fs.bsl
new file mode 100644
index 00000000000..db457dd8de3
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record 04.fs.bsl	
@@ -0,0 +1,30 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Type/Record 04.fs", false, QualifiedNameOfFile Module, [], [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [R],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  Simple
+                    (Record
+                       (None,
+                        [SynField
+                           ([], false, None, FromParseError (5,6--5,6), false,
+                            PreXmlDoc ((5,6), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (5,6--5,6), { LeadingKeyword = None
+                                                MutableKeyword = None })],
+                        (4,4--6,5)), (4,4--6,5)), [], None, (3,5--6,5),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--6,5));
+           Expr (Const (Unit, (8,0--8,2)), (8,0--8,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--8,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(5,6)-(5,7) parse error Unexpected symbol ';' in field declaration. Expected identifier or other token.
diff --git a/tests/service/data/SyntaxTree/Type/Record 05.fs b/tests/service/data/SyntaxTree/Type/Record 05.fs
new file mode 100644
index 00000000000..c74857840e1
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record 05.fs	
@@ -0,0 +1,8 @@
+module Module
+
+type R =
+    { F1: int;
+      ;
+      F3: int }
+
+()
diff --git a/tests/service/data/SyntaxTree/Type/Record 05.fs.bsl b/tests/service/data/SyntaxTree/Type/Record 05.fs.bsl
new file mode 100644
index 00000000000..19883a9e8c9
--- /dev/null
+++ b/tests/service/data/SyntaxTree/Type/Record 05.fs.bsl	
@@ -0,0 +1,42 @@
+ImplFile
+  (ParsedImplFileInput
+     ("/root/Type/Record 05.fs", false, QualifiedNameOfFile Module, [], [],
+      [SynModuleOrNamespace
+         ([Module], false, NamedModule,
+          [Types
+             ([SynTypeDefn
+                 (SynComponentInfo
+                    ([], None, [], [R],
+                     PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
+                     false, None, (3,5--3,6)),
+                  Simple
+                    (Record
+                       (None,
+                        [SynField
+                           ([], false, Some F1,
+                            LongIdent (SynLongIdent ([int], [], [None])), false,
+                            PreXmlDoc ((4,6), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (4,6--4,13), { LeadingKeyword = None
+                                                 MutableKeyword = None });
+                         SynField
+                           ([], false, None, FromParseError (5,6--5,6), false,
+                            PreXmlDoc ((5,6), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (5,6--5,6), { LeadingKeyword = None
+                                                MutableKeyword = None });
+                         SynField
+                           ([], false, Some F3,
+                            LongIdent (SynLongIdent ([int], [], [None])), false,
+                            PreXmlDoc ((6,6), FSharp.Compiler.Xml.XmlDocCollector),
+                            None, (6,6--6,13), { LeadingKeyword = None
+                                                 MutableKeyword = None })],
+                        (4,4--6,15)), (4,4--6,15)), [], None, (3,5--6,15),
+                  { LeadingKeyword = Type (3,0--3,4)
+                    EqualsRange = Some (3,7--3,8)
+                    WithKeyword = None })], (3,0--6,15));
+           Expr (Const (Unit, (8,0--8,2)), (8,0--8,2))],
+          PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+          (1,0--8,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+      { ConditionalDirectives = []
+        CodeComments = [] }, set []))
+
+(5,6)-(5,7) parse error Unexpected symbol ';' in field declaration. Expected identifier or other token.
diff --git a/tests/service/data/SyntaxTree/Type/Struct 02.fs.bsl b/tests/service/data/SyntaxTree/Type/Struct 02.fs.bsl
index 5ed03aa81bd..3ca9cf08ae3 100644
--- a/tests/service/data/SyntaxTree/Type/Struct 02.fs.bsl	
+++ b/tests/service/data/SyntaxTree/Type/Struct 02.fs.bsl	
@@ -16,9 +16,10 @@ ImplFile
                            ([], false, Some Field,
                             LongIdent (SynLongIdent ([int], [], [None])), false,
                             PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (5,12--5,22),
-                            { LeadingKeyword = Some (Val (5,8--5,11)) }),
-                         (5,8--5,22))], (4,4--6,7)), [], None, (3,5--6,7),
+                            None, (5,8--5,22),
+                            { LeadingKeyword = Some (Val (5,8--5,11))
+                              MutableKeyword = None }), (5,8--5,22))],
+                     (4,4--6,7)), [], None, (3,5--6,7),
                   { LeadingKeyword = Type (3,0--3,4)
                     EqualsRange = Some (3,7--3,8)
                     WithKeyword = None })], (3,0--6,7))],
diff --git a/tests/service/data/SyntaxTree/Type/SynTypeDefnWithRecordContainsTheRangeOfTheWithKeyword.fs.bsl b/tests/service/data/SyntaxTree/Type/SynTypeDefnWithRecordContainsTheRangeOfTheWithKeyword.fs.bsl
index 41f5400ce1a..35e334478f0 100644
--- a/tests/service/data/SyntaxTree/Type/SynTypeDefnWithRecordContainsTheRangeOfTheWithKeyword.fs.bsl
+++ b/tests/service/data/SyntaxTree/Type/SynTypeDefnWithRecordContainsTheRangeOfTheWithKeyword.fs.bsl
@@ -20,7 +20,8 @@ ImplFile
                            ([], false, Some Bar,
                             LongIdent (SynLongIdent ([int], [], [None])), false,
                             PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (3,6--3,15), { LeadingKeyword = None })],
+                            None, (3,6--3,15), { LeadingKeyword = None
+                                                 MutableKeyword = None })],
                         (3,4--3,17)), (3,4--3,17)),
                   [Member
                      (SynBinding
diff --git a/tests/service/data/SyntaxTree/Type/SynTypeDefnWithUnionContainsTheRangeOfTheEqualsSign.fs.bsl b/tests/service/data/SyntaxTree/Type/SynTypeDefnWithUnionContainsTheRangeOfTheEqualsSign.fs.bsl
index fdaf263fba8..5e5b3b7fc3b 100644
--- a/tests/service/data/SyntaxTree/Type/SynTypeDefnWithUnionContainsTheRangeOfTheEqualsSign.fs.bsl
+++ b/tests/service/data/SyntaxTree/Type/SynTypeDefnWithUnionContainsTheRangeOfTheEqualsSign.fs.bsl
@@ -23,7 +23,8 @@ ImplFile
                                   LongIdent (SynLongIdent ([int], [], [None])),
                                   false,
                                   PreXmlDoc ((3,16), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (3,16--3,19), { LeadingKeyword = None })],
+                                  None, (3,16--3,19), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((3,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (3,6--3,19), { BarRange = Some (3,4--3,5) });
                          SynUnionCase
@@ -34,13 +35,15 @@ ImplFile
                                   LongIdent (SynLongIdent ([int], [], [None])),
                                   false,
                                   PreXmlDoc ((4,19), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (4,19--4,22), { LeadingKeyword = None });
+                                  None, (4,19--4,22), { LeadingKeyword = None
+                                                        MutableKeyword = None });
                                SynField
                                  ([], false, None,
                                   LongIdent (SynLongIdent ([int], [], [None])),
                                   false,
                                   PreXmlDoc ((4,25), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (4,25--4,28), { LeadingKeyword = None })],
+                                  None, (4,25--4,28), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (4,6--4,28), { BarRange = Some (4,4--4,5) })],
                         (3,4--4,28)), (3,4--4,28)), [], None, (2,5--4,28),
diff --git a/tests/service/data/SyntaxTree/UnionCase/Missing keyword of.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/Missing keyword of.fs.bsl
index 61ef3fc7998..2bac019ca23 100644
--- a/tests/service/data/SyntaxTree/UnionCase/Missing keyword of.fs.bsl	
+++ b/tests/service/data/SyntaxTree/UnionCase/Missing keyword of.fs.bsl	
@@ -37,7 +37,8 @@ ImplFile
                                   LongIdent
                                     (SynLongIdent ([string], [], [None])), false,
                                   PreXmlDoc ((7,12), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (7,12--7,18), { LeadingKeyword = None })],
+                                  None, (7,12--7,18), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((7,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (7,6--7,18), { BarRange = Some (7,4--7,5) });
                          SynUnionCase
@@ -48,7 +49,8 @@ ImplFile
                                   LongIdent (SynLongIdent ([int], [], [None])),
                                   false,
                                   PreXmlDoc ((8,15), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (8,15--8,18), { LeadingKeyword = None })],
+                                  None, (8,15--8,18), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((8,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (8,6--8,18), { BarRange = Some (8,4--8,5) });
                          SynUnionCase
@@ -58,7 +60,8 @@ ImplFile
                                  ([], false, None,
                                   StaticConstant (Int32 4, (9,12--9,13)), false,
                                   PreXmlDoc ((9,12), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (9,12--9,13), { LeadingKeyword = None })],
+                                  None, (9,12--9,13), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((9,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (9,6--9,13), { BarRange = Some (9,4--9,5) })],
                         (6,4--9,13)), (6,4--9,13)), [], None, (5,5--9,13),
diff --git a/tests/service/data/SyntaxTree/UnionCase/Missing name 03.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/Missing name 03.fs.bsl
index f8f3055038c..4a272764df0 100644
--- a/tests/service/data/SyntaxTree/UnionCase/Missing name 03.fs.bsl	
+++ b/tests/service/data/SyntaxTree/UnionCase/Missing name 03.fs.bsl	
@@ -21,7 +21,8 @@ ImplFile
                                   LongIdent (SynLongIdent ([int], [], [None])),
                                   false,
                                   PreXmlDoc ((4,7), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (4,7--4,10), { LeadingKeyword = None })],
+                                  None, (4,7--4,10), { LeadingKeyword = None
+                                                       MutableKeyword = None })],
                             PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (4,4--4,10), { BarRange = None })],
                         (4,4--4,10)), (4,4--4,10)), [], None, (3,5--4,10),
diff --git a/tests/service/data/SyntaxTree/UnionCase/Missing name 04.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/Missing name 04.fs.bsl
index 3d1dfee767b..8913b904cea 100644
--- a/tests/service/data/SyntaxTree/UnionCase/Missing name 04.fs.bsl	
+++ b/tests/service/data/SyntaxTree/UnionCase/Missing name 04.fs.bsl	
@@ -25,7 +25,8 @@ ImplFile
                                   LongIdent (SynLongIdent ([int], [], [None])),
                                   false,
                                   PreXmlDoc ((5,9), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (5,9--5,12), { LeadingKeyword = None })],
+                                  None, (5,9--5,12), { LeadingKeyword = None
+                                                       MutableKeyword = None })],
                             PreXmlDoc ((5,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (5,6--5,12), { BarRange = Some (5,4--5,5) });
                          SynUnionCase
diff --git a/tests/service/data/SyntaxTree/UnionCase/Missing name 05.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/Missing name 05.fs.bsl
index a258d294e96..9d7a69011ef 100644
--- a/tests/service/data/SyntaxTree/UnionCase/Missing name 05.fs.bsl	
+++ b/tests/service/data/SyntaxTree/UnionCase/Missing name 05.fs.bsl	
@@ -25,7 +25,8 @@ ImplFile
                                   LongIdent (SynLongIdent ([int], [], [None])),
                                   false,
                                   PreXmlDoc ((5,18), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (5,18--5,21), { LeadingKeyword = None })],
+                                  None, (5,18--5,21), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((5,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (5,6--5,21), { BarRange = Some (5,4--5,5) });
                          SynUnionCase
diff --git a/tests/service/data/SyntaxTree/UnionCase/MultipleSynUnionCasesHaveBarRange.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/MultipleSynUnionCasesHaveBarRange.fs.bsl
index a3d6304cb9b..8691d476cc6 100644
--- a/tests/service/data/SyntaxTree/UnionCase/MultipleSynUnionCasesHaveBarRange.fs.bsl
+++ b/tests/service/data/SyntaxTree/UnionCase/MultipleSynUnionCasesHaveBarRange.fs.bsl
@@ -21,7 +21,8 @@ ImplFile
                                   LongIdent
                                     (SynLongIdent ([string], [], [None])), false,
                                   PreXmlDoc ((3,13), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (3,13--3,19), { LeadingKeyword = None })],
+                                  None, (3,13--3,19), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((3,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (3,6--3,19), { BarRange = Some (3,4--3,5) });
                          SynUnionCase
@@ -32,7 +33,8 @@ ImplFile
                                   LongIdent (SynLongIdent ([int], [], [None])),
                                   false,
                                   PreXmlDoc ((4,14), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (4,14--4,17), { LeadingKeyword = None })],
+                                  None, (4,14--4,17), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (4,6--4,17), { BarRange = Some (4,4--4,5) })],
                         (3,4--4,17)), (3,4--4,17)), [], None, (2,5--4,17),
diff --git a/tests/service/data/SyntaxTree/UnionCase/PrivateKeywordHasRange.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/PrivateKeywordHasRange.fs.bsl
index 868b74daa10..21d1081b55d 100644
--- a/tests/service/data/SyntaxTree/UnionCase/PrivateKeywordHasRange.fs.bsl
+++ b/tests/service/data/SyntaxTree/UnionCase/PrivateKeywordHasRange.fs.bsl
@@ -21,7 +21,8 @@ ImplFile
                                   LongIdent
                                     (SynLongIdent ([string], [], [None])), false,
                                   PreXmlDoc ((9,14), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (9,14--9,20), { LeadingKeyword = None })],
+                                  None, (9,14--9,20), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((9,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (9,6--9,20), { BarRange = Some (9,4--9,5) })],
                         (7,4--9,20)), (7,4--9,20)), [], None, (2,5--9,20),
diff --git a/tests/service/data/SyntaxTree/UnionCase/Recover Function Type 01.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/Recover Function Type 01.fs.bsl
index 5c804d4a845..4817546864d 100644
--- a/tests/service/data/SyntaxTree/UnionCase/Recover Function Type 01.fs.bsl	
+++ b/tests/service/data/SyntaxTree/UnionCase/Recover Function Type 01.fs.bsl	
@@ -26,7 +26,8 @@ ImplFile
                                      (3,20--3,30), { ArrowRange = (3,24--3,26) }),
                                   false,
                                   PreXmlDoc ((3,20), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (3,20--3,30), { LeadingKeyword = None })],
+                                  None, (3,20--3,30), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((3,11), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (3,13--3,30), { BarRange = Some (3,11--3,12) })],
                         (3,11--3,30)), (3,11--3,30)), [], None, (3,5--3,30),
diff --git a/tests/service/data/SyntaxTree/UnionCase/Recover Function Type 02.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/Recover Function Type 02.fs.bsl
index d73d7a6a397..0b908ef60f6 100644
--- a/tests/service/data/SyntaxTree/UnionCase/Recover Function Type 02.fs.bsl	
+++ b/tests/service/data/SyntaxTree/UnionCase/Recover Function Type 02.fs.bsl	
@@ -26,7 +26,8 @@ ImplFile
                                      (3,19--3,29), { ArrowRange = (3,23--3,25) }),
                                   false,
                                   PreXmlDoc ((3,16), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (3,16--3,29), { LeadingKeyword = None })],
+                                  None, (3,16--3,29), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((3,9), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (3,11--3,29), { BarRange = Some (3,9--3,10) })],
                         (3,9--3,29)), (3,9--3,29)), [], None, (3,5--3,29),
diff --git a/tests/service/data/SyntaxTree/UnionCase/Recover Function Type 03.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/Recover Function Type 03.fs.bsl
index 7ccf1e70d61..97defcda3ce 100644
--- a/tests/service/data/SyntaxTree/UnionCase/Recover Function Type 03.fs.bsl	
+++ b/tests/service/data/SyntaxTree/UnionCase/Recover Function Type 03.fs.bsl	
@@ -31,7 +31,8 @@ ImplFile
                                      (3,16--3,33), { ArrowRange = (3,20--3,22) }),
                                   false,
                                   PreXmlDoc ((3,16), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (3,16--3,33), { LeadingKeyword = None })],
+                                  None, (3,16--3,33), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((3,9), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (3,11--3,33), { BarRange = Some (3,9--3,10) })],
                         (3,9--3,33)), (3,9--3,33)), [], None, (3,5--3,33),
diff --git a/tests/service/data/SyntaxTree/UnionCase/SingleSynUnionCaseHasBarRange.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/SingleSynUnionCaseHasBarRange.fs.bsl
index eaa8e082910..d5c4b3f2f80 100644
--- a/tests/service/data/SyntaxTree/UnionCase/SingleSynUnionCaseHasBarRange.fs.bsl
+++ b/tests/service/data/SyntaxTree/UnionCase/SingleSynUnionCaseHasBarRange.fs.bsl
@@ -21,7 +21,8 @@ ImplFile
                                   LongIdent
                                     (SynLongIdent ([string], [], [None])), false,
                                   PreXmlDoc ((2,20), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (2,20--2,26), { LeadingKeyword = None })],
+                                  None, (2,20--2,26), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((2,11), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (2,13--2,26), { BarRange = Some (2,11--2,12) })],
                         (2,11--2,26)), (2,11--2,26)), [], None, (2,5--2,26),
diff --git a/tests/service/data/SyntaxTree/UnionCase/SingleSynUnionCaseWithoutBar.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/SingleSynUnionCaseWithoutBar.fs.bsl
index 61f328fc6a9..32910732a1c 100644
--- a/tests/service/data/SyntaxTree/UnionCase/SingleSynUnionCaseWithoutBar.fs.bsl
+++ b/tests/service/data/SyntaxTree/UnionCase/SingleSynUnionCaseWithoutBar.fs.bsl
@@ -21,7 +21,8 @@ ImplFile
                                   LongIdent
                                     (SynLongIdent ([string], [], [None])), false,
                                   PreXmlDoc ((2,18), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (2,18--2,24), { LeadingKeyword = None })],
+                                  None, (2,18--2,24), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((2,11), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (2,11--2,24), { BarRange = None })],
                         (2,11--2,24)), (2,11--2,24)), [], None, (2,5--2,24),
diff --git a/tests/service/data/SyntaxTree/UnionCase/UnionCaseFieldsCanHaveComments.fs.bsl b/tests/service/data/SyntaxTree/UnionCase/UnionCaseFieldsCanHaveComments.fs.bsl
index 8ee3e638446..51363b02c37 100644
--- a/tests/service/data/SyntaxTree/UnionCase/UnionCaseFieldsCanHaveComments.fs.bsl
+++ b/tests/service/data/SyntaxTree/UnionCase/UnionCaseFieldsCanHaveComments.fs.bsl
@@ -21,13 +21,15 @@ ImplFile
                                   LongIdent
                                     (SynLongIdent ([string], [], [None])), false,
                                   PreXmlDoc ((6,2), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (5,2--6,15), { LeadingKeyword = None });
+                                  None, (5,2--6,15), { LeadingKeyword = None
+                                                       MutableKeyword = None });
                                SynField
                                  ([], false, None,
                                   LongIdent (SynLongIdent ([bool], [], [None])),
                                   false,
                                   PreXmlDoc ((8,2), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (7,2--8,6), { LeadingKeyword = None })],
+                                  None, (7,2--8,6), { LeadingKeyword = None
+                                                      MutableKeyword = None })],
                             PreXmlDoc ((4,0), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (3,0--8,6), { BarRange = Some (4,0--4,1) })],
                         (3,0--8,6)), (3,0--8,6)), [], None, (2,5--8,6),

From 73d670dc48a30217e241875a9877e90879927ed2 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Mon, 4 Dec 2023 16:53:49 +0100
Subject: [PATCH 51/59] syntax tree layout

---
 .../data/SyntaxTree/Nullness/DuCaseStringOrNull.fs.bsl     | 3 ++-
 .../data/SyntaxTree/Nullness/DuCaseTuplePrecedence.fs.bsl  | 6 ++++--
 .../service/data/SyntaxTree/Nullness/ExplicitField.fs.bsl  | 7 ++++---
 .../data/SyntaxTree/Nullness/RegressionChoiceType.fs.bsl   | 6 ++++--
 .../data/SyntaxTree/Nullness/RegressionListType.fs.bsl     | 6 ++++--
 .../Nullness/RegressionOneLinerOptionType.fs.bsl           | 3 ++-
 .../data/SyntaxTree/Nullness/RegressionResultType.fs.bsl   | 6 ++++--
 7 files changed, 24 insertions(+), 13 deletions(-)

diff --git a/tests/service/data/SyntaxTree/Nullness/DuCaseStringOrNull.fs.bsl b/tests/service/data/SyntaxTree/Nullness/DuCaseStringOrNull.fs.bsl
index ba57735a1a8..fd375837c54 100644
--- a/tests/service/data/SyntaxTree/Nullness/DuCaseStringOrNull.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/DuCaseStringOrNull.fs.bsl
@@ -25,7 +25,8 @@ ImplFile
                                         false, (1,21--1,34)), (1,20--1,35)),
                                   false,
                                   PreXmlDoc ((1,20), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (1,20--1,35), { LeadingKeyword = None })],
+                                  None, (1,20--1,35), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((1,10), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (1,10--1,35), { BarRange = None })],
                         (1,10--1,35)), (1,10--1,35)), [], None, (1,5--1,35),
diff --git a/tests/service/data/SyntaxTree/Nullness/DuCaseTuplePrecedence.fs.bsl b/tests/service/data/SyntaxTree/Nullness/DuCaseTuplePrecedence.fs.bsl
index 379722c41b2..3af1fc28bd5 100644
--- a/tests/service/data/SyntaxTree/Nullness/DuCaseTuplePrecedence.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/DuCaseTuplePrecedence.fs.bsl
@@ -25,13 +25,15 @@ ImplFile
                                         false, (1,21--1,34)), (1,20--1,35)),
                                   false,
                                   PreXmlDoc ((1,20), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (1,20--1,35), { LeadingKeyword = None });
+                                  None, (1,20--1,35), { LeadingKeyword = None
+                                                        MutableKeyword = None });
                                SynField
                                  ([], false, None,
                                   LongIdent (SynLongIdent ([int], [], [None])),
                                   false,
                                   PreXmlDoc ((1,38), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (1,38--1,41), { LeadingKeyword = None })],
+                                  None, (1,38--1,41), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((1,10), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (1,10--1,41), { BarRange = None })],
                         (1,10--1,41)), (1,10--1,41)), [], None, (1,5--1,41),
diff --git a/tests/service/data/SyntaxTree/Nullness/ExplicitField.fs.bsl b/tests/service/data/SyntaxTree/Nullness/ExplicitField.fs.bsl
index b06e92d77eb..93c49b868bf 100644
--- a/tests/service/data/SyntaxTree/Nullness/ExplicitField.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/ExplicitField.fs.bsl
@@ -19,9 +19,10 @@ ImplFile
                               (LongIdent (SynLongIdent ([string], [], [None])),
                                false, (3,31--3,44)), true,
                             PreXmlDoc ((3,8), FSharp.Compiler.Xml.XmlDocCollector),
-                            None, (3,20--3,44),
-                            { LeadingKeyword = Some (Val (3,8--3,11)) }),
-                         (3,8--3,44))], (2,4--4,7)), [], None, (1,5--4,7),
+                            None, (3,8--3,44),
+                            { LeadingKeyword = Some (Val (3,8--3,11))
+                              MutableKeyword = Some (3,12--3,19) }), (3,8--3,44))],
+                     (2,4--4,7)), [], None, (1,5--4,7),
                   { LeadingKeyword = Type (1,0--1,4)
                     EqualsRange = Some (1,14--1,15)
                     WithKeyword = None })], (1,0--4,7))], PreXmlDocEmpty, [],
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionChoiceType.fs.bsl b/tests/service/data/SyntaxTree/Nullness/RegressionChoiceType.fs.bsl
index 3ec9bd46d66..aa2b6752d76 100644
--- a/tests/service/data/SyntaxTree/Nullness/RegressionChoiceType.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionChoiceType.fs.bsl
@@ -30,7 +30,8 @@ ImplFile
                                   Var (SynTypar (T1, None, false), (4,16--4,19)),
                                   false,
                                   PreXmlDoc ((4,16), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (4,16--4,19), { LeadingKeyword = None })],
+                                  None, (4,16--4,19), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((4,2), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (3,2--4,19), { BarRange = Some (4,2--4,3) });
                          SynUnionCase
@@ -41,7 +42,8 @@ ImplFile
                                   Var (SynTypar (T2, None, false), (7,16--7,19)),
                                   false,
                                   PreXmlDoc ((7,16), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (7,16--7,19), { LeadingKeyword = None })],
+                                  None, (7,16--7,19), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((7,2), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (6,2--7,19), { BarRange = Some (7,2--7,3) })],
                         (3,2--7,19)), (3,2--7,19)), [], None, (1,5--7,19),
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionListType.fs.bsl b/tests/service/data/SyntaxTree/Nullness/RegressionListType.fs.bsl
index 481bbb378bc..5b1a914a438 100644
--- a/tests/service/data/SyntaxTree/Nullness/RegressionListType.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionListType.fs.bsl
@@ -41,7 +41,8 @@ ImplFile
                                   Var (SynTypar (T, None, false), (3,23--3,25)),
                                   false,
                                   PreXmlDoc ((3,17), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (3,17--3,25), { LeadingKeyword = None });
+                                  None, (3,17--3,25), { LeadingKeyword = None
+                                                        MutableKeyword = None });
                                SynField
                                  ([], false, Some Tail,
                                   App
@@ -51,7 +52,8 @@ ImplFile
                                         (SynTypar (T, None, false), (3,34--3,36))],
                                      [], None, true, (3,34--3,41)), false,
                                   PreXmlDoc ((3,28), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (3,28--3,41), { LeadingKeyword = None })],
+                                  None, (3,28--3,41), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((3,4), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (3,6--3,41), { BarRange = Some (3,4--3,5) })],
                         (2,4--3,41)), (2,4--3,41)), [], None, (1,5--3,41),
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionOneLinerOptionType.fs.bsl b/tests/service/data/SyntaxTree/Nullness/RegressionOneLinerOptionType.fs.bsl
index 5b785c961d5..7a062070cb7 100644
--- a/tests/service/data/SyntaxTree/Nullness/RegressionOneLinerOptionType.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionOneLinerOptionType.fs.bsl
@@ -25,7 +25,8 @@ ImplFile
                                   LongIdent
                                     (SynLongIdent ([string], [], [None])), false,
                                   PreXmlDoc ((1,35), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (1,35--1,41), { LeadingKeyword = None })],
+                                  None, (1,35--1,41), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((1,25), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (1,27--1,41), { BarRange = Some (1,25--1,26) })],
                         (1,20--1,41)), (1,20--1,41)), [], None, (1,5--1,41),
diff --git a/tests/service/data/SyntaxTree/Nullness/RegressionResultType.fs.bsl b/tests/service/data/SyntaxTree/Nullness/RegressionResultType.fs.bsl
index fea7c9a9a59..c36213899e7 100644
--- a/tests/service/data/SyntaxTree/Nullness/RegressionResultType.fs.bsl
+++ b/tests/service/data/SyntaxTree/Nullness/RegressionResultType.fs.bsl
@@ -30,7 +30,8 @@ ImplFile
                                   Var (SynTypar (T, None, false), (4,26--4,28)),
                                   false,
                                   PreXmlDoc ((4,14), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (4,14--4,28), { LeadingKeyword = None })],
+                                  None, (4,14--4,28), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((4,6), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (3,6--4,28), { BarRange = Some (4,6--4,7) });
                          SynUnionCase
@@ -42,7 +43,8 @@ ImplFile
                                     (SynTypar (TError, None, false),
                                      (7,28--7,35)), false,
                                   PreXmlDoc ((7,17), FSharp.Compiler.Xml.XmlDocCollector),
-                                  None, (7,17--7,35), { LeadingKeyword = None })],
+                                  None, (7,17--7,35), { LeadingKeyword = None
+                                                        MutableKeyword = None })],
                             PreXmlDoc ((7,6), FSharp.Compiler.Xml.XmlDocCollector),
                             None, (6,6--7,35), { BarRange = Some (7,6--7,7) })],
                         (3,6--7,35)), (3,6--7,35)), [], None, (1,9--7,35),

From 80efaa2505f1c905a810d7b1fb2eb2dc517de619 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Tue, 5 Dec 2023 13:16:58 +0100
Subject: [PATCH 52/59] Nullness-related aggressive trimming of FSharp.Core
 (#16387)

---
 src/FSharp.Core/ILLink.LinkAttributes.xml | 6 ++++++
 src/FSharp.Core/ILLink.Substitutions.xml  | 5 +++++
 tests/AheadOfTime/Trimming/check.ps1      | 5 +----
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/src/FSharp.Core/ILLink.LinkAttributes.xml b/src/FSharp.Core/ILLink.LinkAttributes.xml
index 70eba54ff4e..47a3ff01f02 100644
--- a/src/FSharp.Core/ILLink.LinkAttributes.xml
+++ b/src/FSharp.Core/ILLink.LinkAttributes.xml
@@ -169,5 +169,11 @@
     
       
     
+    
+      
+    
+    
+      
+    
   
 
diff --git a/src/FSharp.Core/ILLink.Substitutions.xml b/src/FSharp.Core/ILLink.Substitutions.xml
index 42d44a0b4c4..13ceee32a14 100644
--- a/src/FSharp.Core/ILLink.Substitutions.xml
+++ b/src/FSharp.Core/ILLink.Substitutions.xml
@@ -4,5 +4,10 @@
     
     
     
+
+    
+    
+    
+    
   
 
diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index add84fdd2df..d67d9c3ac88 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -1,7 +1,6 @@
 function CheckTrim($root, $tfm, $outputfile, $expected_len) {
     Write-Host "Publish and Execute: ${tfm} - ${root}"
     Write-Host "Expecting ${expected_len}"
-    Write-Host "CompressAllMetadata value: ${compressAllMetadata}"
 
     $cwd = Get-Location
     Set-Location (Join-Path $PSScriptRoot "${root}")
@@ -39,11 +38,9 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) {
 
 # NOTE: Trimming now errors out on desktop TFMs, as shown below:
 # error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher.
-$compressAllMetadata = $env:_kind -eq "-compressAllMetadata"
-$expectedForSelfContained = if ($compressAllMetadata) {300032} else {288256}
 
 # Check net7.0 trimmed assemblies
-CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len $expectedForSelfContained
+CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len 288256
 
 # Check net7.0 trimmed assemblies
 CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net8.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 8821760 

From bf45deefadc20f9ad9843e5a7dc5164430530802 Mon Sep 17 00:00:00 2001
From: dotnet bot 
Date: Fri, 8 Dec 2023 02:58:39 -0800
Subject: [PATCH 53/59] Merge main to feature/nullness (#16397)

* [main] Update dependencies from dnceng/internal/dotnet-optimization (#16150)

* Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-optimization build 20231019.5

optimization.linux-arm64.MIBC.Runtime , optimization.linux-x64.MIBC.Runtime , optimization.windows_nt-arm64.MIBC.Runtime , optimization.windows_nt-x64.MIBC.Runtime , optimization.windows_nt-x86.MIBC.Runtime
 From Version 1.0.0-prerelease.23515.2 -> To Version 1.0.0-prerelease.23519.5

* Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-optimization build 20231019.5

optimization.linux-arm64.MIBC.Runtime , optimization.linux-x64.MIBC.Runtime , optimization.windows_nt-arm64.MIBC.Runtime , optimization.windows_nt-x64.MIBC.Runtime , optimization.windows_nt-x86.MIBC.Runtime
 From Version 1.0.0-prerelease.23515.2 -> To Version 1.0.0-prerelease.23519.5

* Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-optimization build 20231021.3

optimization.linux-arm64.MIBC.Runtime , optimization.linux-x64.MIBC.Runtime , optimization.windows_nt-arm64.MIBC.Runtime , optimization.windows_nt-x64.MIBC.Runtime , optimization.windows_nt-x86.MIBC.Runtime
 From Version 1.0.0-prerelease.23515.2 -> To Version 1.0.0-prerelease.23521.3

* Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-optimization build 20231021.3

optimization.linux-arm64.MIBC.Runtime , optimization.linux-x64.MIBC.Runtime , optimization.windows_nt-arm64.MIBC.Runtime , optimization.windows_nt-x64.MIBC.Runtime , optimization.windows_nt-x86.MIBC.Runtime
 From Version 1.0.0-prerelease.23515.2 -> To Version 1.0.0-prerelease.23521.3

---------

Co-authored-by: dotnet-maestro[bot] 

* [main] Update dependencies from dotnet/arcade (#16241)

* Update dependencies from https://github.com/dotnet/arcade build 20231106.5

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23556.5

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231106.5

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23556.5

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231106.5

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23556.5

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231106.5

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23556.5

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231106.5

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23556.5

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231106.5

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23556.5

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231106.5

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23556.5

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231114.4

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23564.4

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231130.1

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23580.1

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231130.1

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23580.1

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231130.1

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23580.1

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231130.1

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23580.1

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Update dependencies from https://github.com/dotnet/arcade build 20231130.1

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23580.1

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

---------

Co-authored-by: dotnet-maestro[bot] 
Co-authored-by: Vlad Zarytovskii 
Co-authored-by: Tomas Grosup 

* Name resolution: don't search extension members in type abbreviations (#16390)

* Name resolution: don't search extension members in type abbreviations

* Add test

* Revert "[main] Update dependencies from dotnet/arcade (#16241)" (#16396)

This reverts commit f219a9905961c285d598dcead51936f2c2972263.

* trimmed size updated

---------

Co-authored-by: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Co-authored-by: dotnet-maestro[bot] 
Co-authored-by: Vlad Zarytovskii 
Co-authored-by: Tomas Grosup 
Co-authored-by: Eugene Auduchinok 
---
 eng/Version.Details.xml                       | 20 +++++-----
 eng/Versions.props                            | 10 ++---
 src/Compiler/Checking/NameResolution.fs       |  4 +-
 tests/AheadOfTime/Trimming/check.ps1          |  2 +-
 .../Language/ExtensionMethodTests.fs          | 39 +++++++++++++++++++
 5 files changed, 57 insertions(+), 18 deletions(-)

diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 1f9c76d4095..298f547365c 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -39,25 +39,25 @@
       194f32828726c3f1f63f79f3dc09b9e99c157b11
       
     
-    
+    
       https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
-      0e20c85562e8c4615c2a3a9e28371a34d9d0a398
+      9ecde9217bbd3541f1a9dc2d684b9acfa5f27274
     
-    
+    
       https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
-      0e20c85562e8c4615c2a3a9e28371a34d9d0a398
+      9ecde9217bbd3541f1a9dc2d684b9acfa5f27274
     
-    
+    
       https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
-      0e20c85562e8c4615c2a3a9e28371a34d9d0a398
+      9ecde9217bbd3541f1a9dc2d684b9acfa5f27274
     
-    
+    
       https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
-      0e20c85562e8c4615c2a3a9e28371a34d9d0a398
+      9ecde9217bbd3541f1a9dc2d684b9acfa5f27274
     
-    
+    
       https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
-      0e20c85562e8c4615c2a3a9e28371a34d9d0a398
+      9ecde9217bbd3541f1a9dc2d684b9acfa5f27274
     
   
 
diff --git a/eng/Versions.props b/eng/Versions.props
index 34d16425e05..4ad1130ccd4 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -209,10 +209,10 @@
     2.2.0
     1.0.0-beta.23426.1
     
-    1.0.0-prerelease.23515.2
-    1.0.0-prerelease.23515.2
-    1.0.0-prerelease.23515.2
-    1.0.0-prerelease.23515.2
-    1.0.0-prerelease.23515.2
+    1.0.0-prerelease.23602.3
+    1.0.0-prerelease.23602.3
+    1.0.0-prerelease.23602.3
+    1.0.0-prerelease.23602.3
+    1.0.0-prerelease.23602.3
   
 
diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs
index 6544036b627..a4e45ff3b85 100644
--- a/src/Compiler/Checking/NameResolution.fs
+++ b/src/Compiler/Checking/NameResolution.fs
@@ -578,8 +578,8 @@ let private GetCSharpStyleIndexedExtensionMembersForTyconRef (amap: Import.Impor
     let pri = NextExtensionMethodPriority()
     
     if g.langVersion.SupportsFeature(LanguageFeature.CSharpExtensionAttributeNotRequired) then
-        let csharpStyleExtensionMembers = 
-            if IsTyconRefUsedForCSharpStyleExtensionMembers g m tcrefOfStaticClass || tcrefOfStaticClass.IsLocalRef then
+        let csharpStyleExtensionMembers =
+            if IsTyconRefUsedForCSharpStyleExtensionMembers g m tcrefOfStaticClass || (tcrefOfStaticClass.IsLocalRef && not tcrefOfStaticClass.IsTypeAbbrev) then
                 protectAssemblyExploration [] (fun () ->
                     let ty = generalizedTyconRef g tcrefOfStaticClass
                     GetImmediateIntrinsicMethInfosOfType (None, AccessorDomain.AccessibleFromSomeFSharpCode) g amap m ty
diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index 03827664f3e..373cd534ce2 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -43,5 +43,5 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) {
 CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len 288256
 
 # Check net7.0 trimmed assemblies
-CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net8.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 8821760 
+CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net8.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 8822272 
 
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ExtensionMethodTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ExtensionMethodTests.fs
index 817b33a43d6..510ac830ae4 100644
--- a/tests/FSharp.Compiler.ComponentTests/Language/ExtensionMethodTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Language/ExtensionMethodTests.fs
@@ -609,3 +609,42 @@ type Bar =
             |> withReferences [ fsharp ]
         
         csharp |> compile |> shouldSucceed
+
+    []
+    let ``Abbreviated CSharp type with extensions`` () =
+        let csharp =
+            CSharp """
+namespace CSharpLib {
+
+    public interface I
+    {
+        public int P { get; }
+    }
+
+    public static class Ext
+    {
+        public static void M(this I i)
+        {
+        }
+    }
+}
+    """
+            |> withName "CSLib"
+        
+        let fsharp =
+            FSharp """
+module Module
+
+open CSharpLib
+
+module M =
+    type Ext2 = CSharpLib.Ext
+ 
+    let f (i: I) =
+        i.M()
+"""
+           |> withLangVersion80
+           |> withName "FSLib"
+           |> withReferences [ csharp ]
+        
+        fsharp |> compile |> shouldSucceed

From d697c63082bbec4a228bf20ad2d4b9f72d3b1cf3 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Wed, 17 Jan 2024 18:22:52 +0100
Subject: [PATCH 54/59] Nullness interop - import of C#-emitted metadata
 (#16423)

---
 src/Compiler/AbstractIL/il.fsi                |  20 +-
 src/Compiler/Checking/AccessibilityLogic.fs   |   4 +-
 src/Compiler/Checking/AttributeChecking.fs    |   9 +-
 src/Compiler/Checking/CheckDeclarations.fs    |  18 +-
 src/Compiler/Checking/InfoReader.fs           |   2 +-
 src/Compiler/Checking/NicePrint.fs            |  10 +-
 src/Compiler/Checking/TypeHierarchy.fs        |  31 +-
 src/Compiler/Checking/TypeHierarchy.fsi       |  17 +-
 src/Compiler/Checking/import.fs               | 237 +++++--
 src/Compiler/Checking/import.fsi              |  42 +-
 src/Compiler/Checking/infos.fs                | 144 ++--
 src/Compiler/Checking/infos.fsi               |  10 +-
 src/Compiler/CodeGen/EraseUnions.fs           |   7 +-
 src/Compiler/CodeGen/IlxGen.fs                |  10 +-
 src/Compiler/Symbols/Exprs.fs                 |   7 +-
 src/Compiler/TypedTree/TcGlobals.fs           |   2 +
 src/Compiler/TypedTree/TypedTree.fs           |   3 +-
 src/Compiler/TypedTree/TypedTree.fsi          |   3 +-
 src/Compiler/TypedTree/TypedTreeBasics.fs     |  23 +-
 src/Compiler/Utilities/Activity.fs            |  22 +-
 src/Compiler/Utilities/illib.fs               |  19 +
 src/Compiler/Utilities/illib.fsi              |   2 +
 src/FSharp.Core/prim-types.fs                 |   6 +
 src/FSharp.Core/prim-types.fsi                |   7 +
 tests/AheadOfTime/Trimming/check.ps1          |   2 +-
 .../EmittedIL/Nullness/GenericStructDu.fs     |  11 +
 .../Nullness/GenericStructDu.fs.il.net472.bsl | 644 ++++++++++++++++++
 .../GenericStructDu.fs.il.netcore.bsl         | 415 +++++++++++
 .../EmittedIL/Nullness/NullAsTrueValue.fs     |  12 +-
 .../Nullness/NullAsTrueValue.fs.il.net472.bsl | 483 ++-----------
 .../NullAsTrueValue.fs.il.netcore.bsl         | 416 ++---------
 .../EmittedIL/Nullness/NullnessMetadata.fs    |   5 +
 .../FSharp.Compiler.ComponentTests.fsproj     |   1 +
 .../Language/DiscriminatedUnionTests.fs       |  38 +-
 .../Language/NullableCsharpImportTests.fs     |  85 +++
 ...ervice.SurfaceArea.netstandard20.debug.bsl | 151 ++++
 ...vice.SurfaceArea.netstandard20.release.bsl | 184 ++++-
 tests/FSharp.Test.Utilities/Compiler.fs       |   3 +
 38 files changed, 2130 insertions(+), 975 deletions(-)
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericStructDu.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericStructDu.fs.il.net472.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericStructDu.fs.il.netcore.bsl
 create mode 100644 tests/FSharp.Compiler.ComponentTests/Language/NullableCsharpImportTests.fs

diff --git a/src/Compiler/AbstractIL/il.fsi b/src/Compiler/AbstractIL/il.fsi
index 3fdd7487ddb..8ae223081ac 100644
--- a/src/Compiler/AbstractIL/il.fsi
+++ b/src/Compiler/AbstractIL/il.fsi
@@ -868,7 +868,13 @@ type ILAttributes =
 
 /// Represents the efficiency-oriented storage of ILAttributes in another item.
 []
-type ILAttributesStored
+type ILAttributesStored =
+    /// Computed by ilread.fs based on metadata index
+    | Reader of (int32 -> ILAttribute[])
+    /// Already computed
+    | Given of ILAttributes
+
+    member GetCustomAttrs: int32 -> ILAttributes
 
 /// Method parameters and return values.
 []
@@ -1069,6 +1075,8 @@ type ILMethodDef =
     member IsEntryPoint: bool
     member GenericParams: ILGenericParameterDefs
     member CustomAttrs: ILAttributes
+    member MetadataIndex: int32
+    member CustomAttrsStored: ILAttributesStored
     member ParameterTypes: ILTypes
     member IsIL: bool
     member Code: ILCode option
@@ -1242,6 +1250,10 @@ type ILFieldDef =
 
     member CustomAttrs: ILAttributes
 
+    member MetadataIndex: int32
+
+    member CustomAttrsStored: ILAttributesStored
+
     member IsStatic: bool
 
     member IsSpecialName: bool
@@ -1325,6 +1337,8 @@ type ILEventDef =
     member FireMethod: ILMethodRef option
     member OtherMethods: ILMethodRef list
     member CustomAttrs: ILAttributes
+    member MetadataIndex: int32
+    member CustomAttrsStored: ILAttributesStored
     member IsSpecialName: bool
     member IsRTSpecialName: bool
 
@@ -1387,6 +1401,8 @@ type ILPropertyDef =
     member Init: ILFieldInit option
     member Args: ILTypes
     member CustomAttrs: ILAttributes
+    member MetadataIndex: int32
+    member CustomAttrsStored: ILAttributesStored
     member IsSpecialName: bool
     member IsRTSpecialName: bool
 
@@ -1538,6 +1554,8 @@ type ILTypeDef =
     member Events: ILEventDefs
     member Properties: ILPropertyDefs
     member CustomAttrs: ILAttributes
+    member MetadataIndex: int32
+    member CustomAttrsStored: ILAttributesStored
     member IsClass: bool
     member IsStruct: bool
     member IsInterface: bool
diff --git a/src/Compiler/Checking/AccessibilityLogic.fs b/src/Compiler/Checking/AccessibilityLogic.fs
index 4a70f268ddf..052befa7a0c 100644
--- a/src/Compiler/Checking/AccessibilityLogic.fs
+++ b/src/Compiler/Checking/AccessibilityLogic.fs
@@ -243,8 +243,8 @@ let IsILEventInfoAccessible g amap m ad einfo =
 
 let private IsILMethInfoAccessible g amap m adType ad ilminfo = 
     match ilminfo with 
-    | ILMethInfo (_, ty, None, mdef, _) -> IsILTypeAndMemberAccessible g amap m adType ad (ILTypeInfo.FromType g ty) mdef.Access 
-    | ILMethInfo (_, _, Some declaringTyconRef, mdef, _) -> IsILMemberAccessible g amap m declaringTyconRef ad mdef.Access
+    | ILMethInfo (_, IlType ty, mdef, _) -> IsILTypeAndMemberAccessible g amap m adType ad ty mdef.Access 
+    | ILMethInfo (_, CSharpStyleExtension(declaring=declaringTyconRef), mdef, _) -> IsILMemberAccessible g amap m declaringTyconRef ad mdef.Access
 
 let GetILAccessOfILPropInfo (ILPropInfo(tinfo, pdef)) =
     let tdef = tinfo.RawMetadata
diff --git a/src/Compiler/Checking/AttributeChecking.fs b/src/Compiler/Checking/AttributeChecking.fs
index 2f02f794e8b..977d0ecccc6 100644
--- a/src/Compiler/Checking/AttributeChecking.fs
+++ b/src/Compiler/Checking/AttributeChecking.fs
@@ -90,7 +90,8 @@ type AttribInfo =
          match x with 
          | FSAttribInfo(_g, Attrib(tcref, _, _, _, _, _, _)) -> tcref
          | ILAttribInfo (g, amap, scoref, a, m) -> 
-             let ty = RescopeAndImportILType scoref amap m [] a.Method.DeclaringType
+             // We are skipping nullness check here because this reference is an attribute usage, nullness does not apply.
+             let ty = RescopeAndImportILTypeSkipNullness scoref amap m [] a.Method.DeclaringType
              tcrefOfAppTy g ty
 
     member x.ConstructorArguments = 
@@ -104,7 +105,8 @@ type AttribInfo =
          | ILAttribInfo (_g, amap, scoref, cattr, m) -> 
               let parms, _args = decodeILAttribData cattr 
               [ for argTy, arg in Seq.zip cattr.Method.FormalArgTypes parms ->
-                    let ty = RescopeAndImportILType scoref amap m [] argTy
+                    // We are skipping nullness check here because this reference is an attribute usage, nullness does not apply.
+                    let ty = RescopeAndImportILTypeSkipNullness scoref amap m [] argTy
                     let obj = evalILAttribElem arg
                     ty, obj ]
 
@@ -119,7 +121,8 @@ type AttribInfo =
          | ILAttribInfo (_g, amap, scoref, cattr, m) -> 
               let _parms, namedArgs = decodeILAttribData cattr 
               [ for nm, argTy, isProp, arg in namedArgs ->
-                    let ty = RescopeAndImportILType scoref amap m [] argTy
+                    // We are skipping nullness check here because this reference is an attribute usage, nullness does not apply.
+                    let ty = RescopeAndImportILTypeSkipNullness scoref amap m [] argTy
                     let obj = evalILAttribElem arg
                     let isField = not isProp 
                     ty, nm, isField, obj ]
diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs
index c393012d631..1a958832ce6 100644
--- a/src/Compiler/Checking/CheckDeclarations.fs
+++ b/src/Compiler/Checking/CheckDeclarations.fs
@@ -4708,14 +4708,16 @@ module TcDeclarations =
         MutRecBindingChecking.TcMutRecDefns_UpdateModuleContents mutRecNSInfo mutRecDefnsAfterVals
 
         // Generate the union augmentation values for all tycons.
-        (envMutRec, mutRecDefnsAfterCore) ||> MutRecShapes.iterTyconsWithEnv (fun envForDecls ((tyconCore, _, _), tyconOpt, _, _, _) -> 
-            let (MutRecDefnsPhase1DataForTycon (isAtOriginalTyconDefn=isAtOriginalTyconDefn)) = tyconCore
-            match tyconOpt with 
-            | Some tycon when isAtOriginalTyconDefn -> 
-                if tycon.IsUnionTycon && AddAugmentationDeclarations.ShouldAugmentUnion cenv.g tycon then
-                    let vspecs = AddAugmentationDeclarations.AddUnionAugmentationValues cenv envForDecls tycon
-                    ignore vspecs
-            | _ -> ())
+        // TODO nullness :: this is the handling of DU .Is* properties WITHIN signature files.
+        // Watch https://github.com/fsharp/fslang-design/discussions
+        //(envMutRec, mutRecDefnsAfterCore) ||> MutRecShapes.iterTyconsWithEnv (fun envForDecls ((tyconCore, _, _), tyconOpt, _, _, _) -> 
+        //    let (MutRecDefnsPhase1DataForTycon (isAtOriginalTyconDefn=isAtOriginalTyconDefn)) = tyconCore
+        //    match tyconOpt with 
+        //    | Some tycon when isAtOriginalTyconDefn -> 
+        //        if tycon.IsUnionTycon && AddAugmentationDeclarations.ShouldAugmentUnion cenv.g tycon then
+        //            let vspecs = AddAugmentationDeclarations.AddUnionAugmentationValues cenv envForDecls tycon
+        //            ignore vspecs
+        //    | _ -> ())
 
         envMutRec
 
diff --git a/src/Compiler/Checking/InfoReader.fs b/src/Compiler/Checking/InfoReader.fs
index 8f5489b0c6a..c006dc916cf 100644
--- a/src/Compiler/Checking/InfoReader.fs
+++ b/src/Compiler/Checking/InfoReader.fs
@@ -1142,7 +1142,7 @@ let GetXmlDocSigOfMethInfo (infoReader: InfoReader)  m (minfo: MethInfo) =
         match TryFindMetadataInfoOfExternalEntityRef infoReader m ilminfo.DeclaringTyconRef  with 
         | None -> None
         | Some (ccuFileName, formalTypars, formalTypeInfo) ->
-            let filminfo = ILMethInfo(g, formalTypeInfo.ToType, None, ilminfo.RawMetadata, fmtps) 
+            let filminfo = ILMethInfo(g, IlType formalTypeInfo, ilminfo.RawMetadata, fmtps) 
             let args = 
                 if ilminfo.IsILExtensionMethod then
                     filminfo.GetRawArgTypes(amap, m, minfo.FormalMethodInst)
diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs
index a846b62f3d8..718fcc7610c 100644
--- a/src/Compiler/Checking/NicePrint.fs
+++ b/src/Compiler/Checking/NicePrint.fs
@@ -1646,14 +1646,14 @@ module InfoMemberPrinting =
 
     // Prettify an ILMethInfo
     let prettifyILMethInfo (amap: Import.ImportMap) m (minfo: MethInfo) typarInst ilMethInfo = 
-        let (ILMethInfo(_, apparentTy, dty, mdef, _)) = ilMethInfo
-        let (prettyTyparInst, prettyTys), _ = PrettyTypes.PrettifyInstAndTypes amap.g (typarInst, (apparentTy :: minfo.FormalMethodInst))
+        let (ILMethInfo(_, methodsType, mdef, _)) = ilMethInfo
+        let (prettyTyparInst, prettyTys), _ = PrettyTypes.PrettifyInstAndTypes amap.g (typarInst, (methodsType.ToType :: minfo.FormalMethodInst))
         match prettyTys with
         | prettyApparentTy :: prettyFormalMethInst ->
             let prettyMethInfo = 
-                match dty with 
-                | None -> MethInfo.CreateILMeth (amap, m, prettyApparentTy, mdef)
-                | Some declaringTyconRef -> MethInfo.CreateILExtensionMeth(amap, m, prettyApparentTy, declaringTyconRef, minfo.ExtensionMemberPriorityOption, mdef)
+                match methodsType with 
+                | IlType _ -> MethInfo.CreateILMeth (amap, m, prettyApparentTy, mdef)
+                | CSharpStyleExtension(declaring=declaringTyconRef) -> MethInfo.CreateILExtensionMeth(amap, m, prettyApparentTy, declaringTyconRef, minfo.ExtensionMemberPriorityOption, mdef)
             prettyTyparInst, prettyMethInfo, prettyFormalMethInst
         | _ -> failwith "prettifyILMethInfo - prettyTys empty"
 
diff --git a/src/Compiler/Checking/TypeHierarchy.fs b/src/Compiler/Checking/TypeHierarchy.fs
index b4c2e965f25..a629857245a 100644
--- a/src/Compiler/Checking/TypeHierarchy.fs
+++ b/src/Compiler/Checking/TypeHierarchy.fs
@@ -55,7 +55,8 @@ let GetSuperTypeOfType g amap m ty =
             let tinst = argsOfAppTy g ty
             match tdef.Extends with
             | None -> None
-            | Some ilTy -> Some (RescopeAndImportILType scoref amap m tinst ilTy)
+                                // 'inherit' cannot refer to a nullable type
+            | Some ilTy -> Some (RescopeAndImportILTypeSkipNullness scoref amap m tinst ilTy)
 
         | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata ->
             if isFSharpObjModelTy g ty || isFSharpExceptionTy g ty then
@@ -115,7 +116,8 @@ let GetImmediateInterfacesOfMetadataType g amap m skipUnref ty (tcref: TyconRef)
             // assume those are present.
             for intfTy in tdef.Implements do
                 if skipUnref = SkipUnrefInterfaces.No || CanRescopeAndImportILType scoref amap m intfTy then
-                    RescopeAndImportILType scoref amap m tinst intfTy
+                    // Implementing an interface cannot refer to a nullable type
+                    RescopeAndImportILTypeSkipNullness scoref amap m tinst intfTy
         | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata ->
             for intfTy in tcref.ImmediateInterfaceTypesOfFSharpTycon do
                instType (mkInstForAppTy g ty) intfTy ]
@@ -356,33 +358,38 @@ let ExistsHeadTypeInEntireHierarchy g amap m typeToSearchFrom tcrefToLookFor =
     ExistsInEntireHierarchyOfType (HasHeadType g tcrefToLookFor) g amap m AllowMultiIntfInstantiations.Yes typeToSearchFrom
 
 /// Read an Abstract IL type from metadata and convert to an F# type.
-let ImportILTypeFromMetadata amap m scoref tinst minst ilTy =
-    RescopeAndImportILType scoref amap m (tinst@minst) ilTy
+let ImportILTypeFromMetadata amap m scoref tinst minst nullnessSource ilTy =
+    RescopeAndImportILType scoref amap m (tinst@minst) nullnessSource ilTy
+
+/// Read an Abstract IL type from metadata and convert to an F# type, ignoring nullness checking.
+let ImportILTypeFromMetadataSkipNullness amap m scoref tinst minst ilTy =
+    RescopeAndImportILTypeSkipNullness scoref amap m (tinst@minst) ilTy
 
 /// Read an Abstract IL type from metadata, including any attributes that may affect the type itself, and convert to an F# type.
-let ImportILTypeFromMetadataWithAttributes amap m scoref tinst minst ilTy getCattrs =
-    let ty = RescopeAndImportILType scoref amap m (tinst@minst) ilTy
+let ImportILTypeFromMetadataWithAttributes amap m scoref tinst minst nullnessSource ilTy =
+    let ty = RescopeAndImportILType scoref amap m (tinst@minst) nullnessSource ilTy
+
     // If the type is a byref and one of attributes from a return or parameter has
     // - a `IsReadOnlyAttribute` - it's an inref
     // - a `RequiresLocationAttribute` (in which case it's a `ref readonly`) which we treat as inref,
     // latter is an ad-hoc fix for https://github.com/dotnet/runtime/issues/94317.
     if isByrefTy amap.g ty
-       && (TryFindILAttribute amap.g.attrib_IsReadOnlyAttribute (getCattrs ())
-           || TryFindILAttribute amap.g.attrib_RequiresLocationAttribute (getCattrs ())) then
+       && (TryFindILAttribute amap.g.attrib_IsReadOnlyAttribute (nullnessSource.DirectAttributes.Read())
+           || TryFindILAttribute amap.g.attrib_RequiresLocationAttribute (nullnessSource.DirectAttributes.Read())) then
         mkInByrefTy amap.g (destByrefTy amap.g ty)
     else
         ty
 
 /// Get the parameter type of an IL method.
-let ImportParameterTypeFromMetadata amap m ilTy getCattrs scoref tinst mist =
-    ImportILTypeFromMetadataWithAttributes amap m scoref tinst mist ilTy getCattrs
+let ImportParameterTypeFromMetadata amap m nullnessSource ilTy scoref tinst mist =   
+    ImportILTypeFromMetadataWithAttributes amap m scoref tinst mist nullnessSource ilTy
 
 /// Get the return type of an IL method, taking into account instantiations for type, return attributes and method generic parameters, and
 /// translating 'void' to 'None'.
-let ImportReturnTypeFromMetadata amap m ilTy getCattrs scoref tinst minst =
+let ImportReturnTypeFromMetadata amap m nullnessSource ilTy scoref tinst minst =  
     match ilTy with
     | ILType.Void -> None
-    | retTy -> Some(ImportILTypeFromMetadataWithAttributes amap m scoref tinst minst retTy getCattrs)
+    | retTy -> Some(ImportILTypeFromMetadataWithAttributes amap m scoref tinst minst nullnessSource retTy )
 
 
 /// Copy constraints.  If the constraint comes from a type parameter associated
diff --git a/src/Compiler/Checking/TypeHierarchy.fsi b/src/Compiler/Checking/TypeHierarchy.fsi
index 225e6187477..8633f9827f9 100644
--- a/src/Compiler/Checking/TypeHierarchy.fsi
+++ b/src/Compiler/Checking/TypeHierarchy.fsi
@@ -117,6 +117,17 @@ val ExistsHeadTypeInEntireHierarchy:
 
 /// 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 ->
+    nullnessSource: Nullness.NullableAttributesSource ->
+    ilTy: ILType ->
+        TType
+
+/// Read an Abstract IL type from metadata and convert to an F# type, ignoring nullness checking.
+val ImportILTypeFromMetadataSkipNullness:
     amap: ImportMap -> m: range -> scoref: ILScopeRef -> tinst: TType list -> minst: TType list -> ilTy: ILType -> TType
 
 /// Read an Abstract IL type from metadata, including any attributes that may affect the type itself, and convert to an F# type.
@@ -126,16 +137,16 @@ val ImportILTypeFromMetadataWithAttributes:
     scoref: ILScopeRef ->
     tinst: TType list ->
     minst: TType list ->
+    nullnessSource: Nullness.NullableAttributesSource ->
     ilTy: ILType ->
-    getCattrs: (unit -> ILAttributes) ->
         TType
 
 /// Get the parameter type of an IL method.
 val ImportParameterTypeFromMetadata:
     amap: ImportMap ->
     m: range ->
+    nullnessSource: Nullness.NullableAttributesSource ->
     ilTy: ILType ->
-    getCattrs: (unit -> ILAttributes) ->
     scoref: ILScopeRef ->
     tinst: TType list ->
     mist: TType list ->
@@ -146,8 +157,8 @@ val ImportParameterTypeFromMetadata:
 val ImportReturnTypeFromMetadata:
     amap: ImportMap ->
     m: range ->
+    nullnessSource: Nullness.NullableAttributesSource ->
     ilTy: ILType ->
-    getCattrs: (unit -> ILAttributes) ->
     scoref: ILScopeRef ->
     tinst: TType list ->
     minst: TType list ->
diff --git a/src/Compiler/Checking/import.fs b/src/Compiler/Checking/import.fs
index 6621600d7f5..f629df6c5e9 100644
--- a/src/Compiler/Checking/import.fs
+++ b/src/Compiler/Checking/import.fs
@@ -166,21 +166,115 @@ let CanImportILTypeRef (env: ImportMap) m (tref: ILTypeRef) =
 let ImportTyconRefApp (env: ImportMap) tcref tyargs nullness = 
     env.g.improveType tcref tyargs nullness
 
-let ImportNullness (g: TcGlobals) =
-    ignore g
-    // if g.langFeatureNullness && g.assumeNullOnImport then
-    //     KnownWithNull
-    // else
-    // TODO NULLNESS
-    KnownAmbivalentToNull
-
-let ImportNullnessForTyconRef (g: TcGlobals) (m: range) (tcref: TyconRef) =
-    ignore (g, tcref, m)
-    // if g.langFeatureNullness && g.assumeNullOnImport && TyconRefNullIsExtraValue g m tcref then
-    //     KnownWithNull
-    // else
-    // TODO NULLNESS
-    KnownAmbivalentToNull
+
+module Nullness =
+
+    open FSharp.Compiler.AbstractIL.Diagnostics
+
+    let arrayWithByte0 = [|0uy|]
+    let arrayWithByte1 = [|1uy|]
+    let arrayWithByte2 = [|2uy|]
+
+    let knownAmbivalent = NullnessInfo.AmbivalentToNull |> Nullness.Known
+    let knownWithoutNull = NullnessInfo.WithoutNull |> Nullness.Known
+    let knownNullable = NullnessInfo.WithNull |> Nullness.Known
+
+    let mapping byteValue = 
+        match byteValue with
+        | 0uy -> knownAmbivalent
+        | 1uy -> knownWithoutNull
+        | 2uy -> knownNullable
+        | _ ->
+            dprintfn "%i was passed to Nullness mapping, this is not a valid value" byteValue
+            knownAmbivalent         
+
+    let tryParseAttributeDataToNullableByteFlags (g:TcGlobals) attrData = 
+        match attrData with
+        | None -> ValueNone
+        | Some ([ILAttribElem.Byte 0uy],_) -> ValueSome arrayWithByte0
+        | Some ([ILAttribElem.Byte 1uy],_) -> ValueSome arrayWithByte1
+        | Some ([ILAttribElem.Byte 2uy],_) -> ValueSome arrayWithByte2
+        | Some ([ILAttribElem.Array(byteType,listOfBytes)],_) when byteType = g.ilg.typ_Byte -> 
+            listOfBytes
+            |> Array.ofList
+            |> Array.choose(function | ILAttribElem.Byte b -> Some b | _ -> None)
+            |> ValueSome
+            
+        | _ -> ValueNone
+
+    []
+    type AttributesFromIL = AttributesFromIL of metadataIndex:int * attrs:ILAttributesStored
+        with 
+            member this.Read() =  match this with| AttributesFromIL(idx,attrs) -> attrs.GetCustomAttrs(idx)
+            member this.GetNullable(g:TcGlobals) = 
+                match g.attrib_NullableAttribute_opt with
+                | None -> ValueNone
+                | Some n ->
+                    TryDecodeILAttribute n.TypeRef (this.Read())
+                    |> tryParseAttributeDataToNullableByteFlags g
+
+            member this.GetNullableContext(g:TcGlobals) = 
+                match g.attrib_NullableContextAttribute_opt with
+                | None -> ValueNone
+                | Some n ->
+                    TryDecodeILAttribute n.TypeRef (this.Read())
+                    |> tryParseAttributeDataToNullableByteFlags g
+
+    []
+    type NullableContextSource = 
+        | FromClass of AttributesFromIL
+        | FromMethodAndClass of methodAttrs:AttributesFromIL * classAttrs:AttributesFromIL
+
+    []
+    type NullableAttributesSource =
+        { DirectAttributes: AttributesFromIL
+          Fallback : NullableContextSource}
+          with
+            member this.GetFlags(g:TcGlobals) = 
+                let fallback = this.Fallback
+                this.DirectAttributes.GetNullable(g)
+                |> ValueOption.orElseWith(fun () -> 
+                    match fallback with
+                    | FromClass attrs -> attrs.GetNullableContext(g)
+                    | FromMethodAndClass(methodCtx,classCtx) -> 
+                        methodCtx.GetNullableContext(g)
+                        |> ValueOption.orElseWith (fun () -> classCtx.GetNullableContext(g)))
+                |> ValueOption.defaultValue arrayWithByte0
+            static member Empty = 
+                let emptyFromIL = AttributesFromIL(0,Given(ILAttributes.Empty))
+                {DirectAttributes = emptyFromIL; Fallback = FromClass(emptyFromIL)}
+
+    []
+    type NullableFlags = {Data : byte[]; Idx : int }
+(* Nullness logic for generic arguments:
+The data which comes from NullableAttribute back might be a flat array, or a scalar (which represents a virtual array of unknown size)
+The array is passed trough all generic typars depth first , e.g.  List,Uri>>
+        -- see here how the array indexes map to types above:   [| 0    1     2   3    4      5 |]
+For value types, a value is passed even though it is always 0
+*)
+        with
+            member this.GetNullness() = 
+                match this.Data.Length with
+                // No nullable data nor parent context -> we cannot tell
+                | 0 -> knownAmbivalent 
+                // A scalar value from attributes, cover type and all it's potential typars
+                | 1 -> this.Data[0] |> mapping
+                // We have a bigger array, indexes map to typars in a depth-first fashion
+                | n when n > this.Idx -> this.Data[this.Idx] |> mapping
+                // This is an errornous case, we need more nullnessinfo then the metadata contains
+                | _ -> 
+                    failwithf "Length of Nullable metadata and needs of its processing do not match:  %A" this // TODO nullness - once being confident that our bugs are solved and what remains are incoming metadata bugs, remove failwith and replace with dprintfn
+                    knownAmbivalent
+
+            member this.Advance() = {Data = this.Data; Idx = this.Idx + 1}
+
+    let inline evaluateFirstOrderNullnessAndAdvance (ilt:ILType) (flags:NullableFlags) = 
+        match ilt with
+        | ILType.Value tspec when tspec.GenericArgs.IsEmpty -> KnownWithoutNull, flags
+        // TODO nullness - System.Nullable might be tricky, since you CAN assign 'null' to it, and when boxed, it CAN be boxed to 'null'.
+        | ILType.Value tspec when tspec.Name = "Nullable`1" && tspec.Enclosing = ["System"] -> KnownWithoutNull, flags
+        | ILType.Value _  -> KnownWithoutNull, flags.Advance()
+        | _ -> flags.GetNullness(), flags.Advance()
 
 /// Import an IL type as an F# type.
 let rec ImportILType (env: ImportMap) m tinst ty =  
@@ -190,27 +284,20 @@ let rec ImportILType (env: ImportMap) m tinst ty =
 
     | ILType.Array(bounds, ty) -> 
         let n = bounds.Rank
-        let elemTy = ImportILType env m tinst ty
-        let nullness = ImportNullness env.g
-        mkArrayTy env.g n nullness elemTy m
+        let elemTy = ImportILType env m tinst ty     
+        mkArrayTy env.g n Nullness.knownAmbivalent elemTy m
 
     | ILType.Boxed  tspec | ILType.Value tspec ->
         let tcref = ImportILTypeRef env m tspec.TypeRef 
-        let inst = tspec.GenericArgs |> List.map (ImportILType env m tinst) 
-        let nullness = ImportNullnessForTyconRef env.g m tcref
-        ImportTyconRefApp env tcref inst nullness
+        let inst = tspec.GenericArgs |> List.map (ImportILType env m tinst)        
+        ImportTyconRefApp env tcref inst Nullness.knownAmbivalent
 
     | ILType.Byref ty -> mkByrefTy env.g (ImportILType env m tinst ty)
-
     | ILType.Ptr ILType.Void  when env.g.voidptr_tcr.CanDeref -> mkVoidPtrTy env.g
-
     | ILType.Ptr ty  -> mkNativePtrTy env.g (ImportILType env m tinst ty)
-
     | ILType.FunctionPointer _ -> env.g.nativeint_ty (* failwith "cannot import this kind of type (ptr, fptr)" *)
-
     | ILType.Modified(_, _, ty) -> 
-         // All custom modifiers are ignored
-         // NULLNESS TODO: pick up the optional attributes at this point and fold the array of nullness information into the conversion
+         // All custom modifiers are ignored       
          ImportILType env m tinst ty
 
     | ILType.TypeVar u16 -> 
@@ -219,30 +306,69 @@ let rec ImportILType (env: ImportMap) m tinst ty =
                 List.item (int u16) tinst
             with _ -> 
                 error(Error(FSComp.SR.impNotEnoughTypeParamsInScopeWhileImporting(), m))
-        let nullness = ImportNullness env.g
-        let tyWithNullness = addNullnessToTy nullness ty
+
+        let tyWithNullness = addNullnessToTy Nullness.knownAmbivalent ty
         tyWithNullness
 
+/// Import an IL type as an F# type.
+let rec ImportILTypeWithNullness (env: ImportMap) m tinst (nf:Nullness.NullableFlags) ty : struct(TType*Nullness.NullableFlags) =  
+    match ty with
+    | ILType.Void -> 
+        env.g.unit_ty,nf
+
+    | ILType.Array(bounds, ty) -> 
+        let n = bounds.Rank
+        let (arrayNullness,nf) = Nullness.evaluateFirstOrderNullnessAndAdvance ty nf
+        let struct(elemTy,nf) = ImportILTypeWithNullness env m tinst nf ty
+        mkArrayTy env.g n arrayNullness elemTy m, nf
+
+    | ILType.Boxed  tspec | ILType.Value tspec ->
+        let tcref = ImportILTypeRef env m tspec.TypeRef 
+        let (typeRefNullness,nf) = Nullness.evaluateFirstOrderNullnessAndAdvance ty nf
+        let struct(inst,nullableFlagsLeft) = (nf,tspec.GenericArgs) ||> List.vMapFold (fun nf current -> ImportILTypeWithNullness env m tinst nf current )
+
+        ImportTyconRefApp env tcref inst typeRefNullness, nullableFlagsLeft
+
+    | ILType.Byref ty -> 
+        let struct(ttype,nf) = ImportILTypeWithNullness env m tinst nf ty 
+        mkByrefTy env.g ttype, nf
+
+    | ILType.Ptr ILType.Void  when env.g.voidptr_tcr.CanDeref -> mkVoidPtrTy env.g, nf
+
+    | ILType.Ptr ty  -> 
+        let struct(ttype,nf) = ImportILTypeWithNullness env m tinst nf ty 
+        mkNativePtrTy env.g ttype, nf
+
+    | ILType.FunctionPointer _ -> env.g.nativeint_ty, nf (* failwith "cannot import this kind of type (ptr, fptr)" *)
+
+    | ILType.Modified(_, _, ty) -> 
+         // All custom modifiers are ignored       
+         ImportILTypeWithNullness env m tinst nf ty 
+
+    | ILType.TypeVar u16 -> 
+        let ttype = 
+            try 
+                List.item (int u16) tinst
+            with _ -> 
+                error(Error(FSComp.SR.impNotEnoughTypeParamsInScopeWhileImporting(), m))
+
+        let (typeVarNullness,nf) = Nullness.evaluateFirstOrderNullnessAndAdvance ty nf
+        addNullnessToTy typeVarNullness ttype, nf
+
 /// Determines if an IL type can be imported as an F# type
 let rec CanImportILType (env: ImportMap) m ty =  
     match ty with
     | ILType.Void -> true
-
     | ILType.Array(_bounds, ety) -> CanImportILType env m ety
-
     | ILType.Boxed  tspec
     | ILType.Value tspec ->
         CanImportILTypeRef env m tspec.TypeRef 
         && tspec.GenericArgs |> List.forall (CanImportILType env m) 
 
     | ILType.Byref ety -> CanImportILType env m ety
-
     | ILType.Ptr ety  -> CanImportILType env m ety
-
     | ILType.FunctionPointer _ -> true
-
     | ILType.Modified(_, _, ety) -> CanImportILType env m ety
-
     | ILType.TypeVar _u16 -> true
 
 #if !NO_TYPEPROVIDERS
@@ -307,7 +433,7 @@ let rec ImportProvidedType (env: ImportMap) (m: range) (* (tinst: TypeInst) *) (
     let g = env.g
     if st.PUntaint((fun st -> st.IsArray), m) then 
         let elemTy = ImportProvidedType env m (* tinst *) (st.PApply((fun st -> st.GetElementType()), m))
-        let nullness = ImportNullness env.g
+        let nullness = Nullness.knownAmbivalent // TODO nullness import :: type providers  Nullness.ImportNullness env.g
         mkArrayTy g (st.PUntaint((fun st -> st.GetArrayRank()), m)) nullness elemTy m
     elif st.PUntaint((fun st -> st.IsByRef), m) then 
         let elemTy = ImportProvidedType env m (* tinst *) (st.PApply((fun st -> st.GetElementType()), m))
@@ -380,7 +506,7 @@ let rec ImportProvidedType (env: ImportMap) (m: range) (* (tinst: TypeInst) *) (
                 else
                     genericArg)
 
-        let nullness = ImportNullnessForTyconRef env.g m tcref
+        let nullness = Nullness.knownAmbivalent // TODO nullness import ::  type providers Nullness.ImportNullnessForTyconRef env.g m tcref
 
         ImportTyconRefApp env tcref genericArgs nullness
 
@@ -433,6 +559,7 @@ let ImportProvidedMethodBaseAsILMethodRef (env: ImportMap) (m: range) (mbase: Ta
                        let formalParamTysAfterInst = 
                            [ for p in ctor.PApplyArray((fun x -> x.GetParameters()), "GetParameters", m) do
                                 let ilFormalTy = ImportProvidedTypeAsILType env m (p.PApply((fun p -> p.ParameterType), m))
+                                // TODO nullness import ::  of Nullness in type providers
                                 yield ImportILType env m actualGenericArgs ilFormalTy ]
 
                        (formalParamTysAfterInst, actualParamTys) ||>  List.lengthsEqAndForall2 (typeEquiv env.g))
@@ -479,7 +606,7 @@ let ImportProvidedMethodBaseAsILMethodRef (env: ImportMap) (m: range) (mbase: Ta
 /// 
 /// Fixup the constraints so that any references to the generic parameters
 /// in the constraints now refer to the new generic parameters.
-let ImportILGenericParameters amap m scoref tinst (gps: ILGenericParameterDefs) = 
+let ImportILGenericParameters amap m scoref tinst (nullableFallback:Nullness.NullableContextSource) (gps: ILGenericParameterDefs) = 
     match gps with 
     | [] -> []
     | _ -> 
@@ -490,7 +617,19 @@ let ImportILGenericParameters amap m scoref tinst (gps: ILGenericParameterDefs)
         let importInst = tinst@tptys
         (tps, gps) ||> List.iter2 (fun tp gp -> 
             let constraints = 
-                [ if gp.CustomAttrs |> TryFindILAttribute amap.g.attrib_IsUnmanagedAttribute then
+                [  
+                  if amap.g.langFeatureNullness && amap.g.checkNullness then
+                    let nullness = 
+                        {   Nullness.DirectAttributes = Nullness.AttributesFromIL(gp.MetadataIndex,gp.CustomAttrsStored)
+                            Nullness.Fallback = nullableFallback }
+               
+                    match nullness.GetFlags(amap.g) with
+                    |  [|1uy|] -> TyparConstraint.NotSupportsNull(m)
+                    // In F#, 'SupportsNull' has the meaning of "must support null as a value". In C#, Nullable(2) is an allowance, not a requirement.
+                    //|  [|2uy|] -> TyparConstraint.SupportsNull(m)
+                    | _ -> ()           
+               
+                  if gp.CustomAttrs |> TryFindILAttribute amap.g.attrib_IsUnmanagedAttribute then
                     TyparConstraint.IsUnmanaged(m)
                   if gp.HasDefaultConstructorConstraint then
                     TyparConstraint.RequiresDefaultConstructor(m)
@@ -541,13 +680,15 @@ let rec ImportILTypeDef amap m scoref (cpath: CompilationPath) enc nm (tdef: ILT
             ImportILTypeDefs amap m scoref cpath (enc@[tdef]) tdef.NestedTypes
         )
 
+    let nullableFallback = Nullness.FromClass(Nullness.AttributesFromIL(tdef.MetadataIndex,tdef.CustomAttrsStored))
+
     // Add the type itself. 
     Construct.NewILTycon 
         (Some cpath) 
         (nm, m) 
         // The read of the type parameters may fail to resolve types. We pick up a new range from the point where that read is forced
         // Make sure we reraise the original exception one occurs - see findOriginalException.
-        (LazyWithContext.Create((fun m -> ImportILGenericParameters amap m scoref [] tdef.GenericParams), findOriginalException))
+        (LazyWithContext.Create((fun m -> ImportILGenericParameters amap m scoref [] nullableFallback tdef.GenericParams), findOriginalException))
         (scoref, enc, tdef) 
         (MaybeLazy.Lazy lazyModuleOrNamespaceTypeForNestedTypes)
        
@@ -725,13 +866,25 @@ let ImportILAssembly(amap: unit -> ImportMap, m, auxModuleLoader, xmlDocInfoLoad
     CcuThunk.Create(nm, ccuData)
 
 //-------------------------------------------------------------------------
-// From IL types to F# types
+// From IL types to F# typess
 //-------------------------------------------------------------------------
 
 /// Import an IL type as an F# type. importInst gives the context for interpreting type variables.
-let RescopeAndImportILType scoref amap m importInst ilTy =
+let RescopeAndImportILTypeSkipNullness scoref amap m importInst ilTy =
     ilTy |> rescopeILType scoref |>  ImportILType amap m importInst
 
+let RescopeAndImportILType scoref (amap:ImportMap) m importInst (nullnessSource:Nullness.NullableAttributesSource) ilTy =
+    let g = amap.g
+    if g.langFeatureNullness && g.checkNullness then
+        let flags = nullnessSource.GetFlags(g)
+        let flags = {Nullness.NullableFlags.Data = flags; Nullness.NullableFlags.Idx = 0}
+        let struct(ty,_) = ilTy |> rescopeILType scoref |>  ImportILTypeWithNullness amap m importInst flags
+        ty
+    else
+        RescopeAndImportILTypeSkipNullness scoref amap m importInst ilTy
+
+
+
 let CanRescopeAndImportILType scoref amap m ilTy =
     ilTy |> rescopeILType scoref |>  CanImportILType amap m
 
diff --git a/src/Compiler/Checking/import.fsi b/src/Compiler/Checking/import.fsi
index 830fd81b12d..fb1f191effc 100644
--- a/src/Compiler/Checking/import.fsi
+++ b/src/Compiler/Checking/import.fsi
@@ -51,6 +51,26 @@ type ImportMap =
     /// The TcGlobals for the import context
     member g: TcGlobals
 
+module Nullness =
+
+    []
+    type AttributesFromIL =
+        | AttributesFromIL of metadataIndex: int * attrs: ILAttributesStored
+
+        member Read: unit -> ILAttributes
+
+    []
+    type NullableContextSource =
+        | FromClass of AttributesFromIL
+        | FromMethodAndClass of methodAttrs: AttributesFromIL * classAttrs: AttributesFromIL
+
+    []
+    type NullableAttributesSource =
+        { DirectAttributes: AttributesFromIL
+          Fallback: NullableContextSource }
+
+        static member Empty: NullableAttributesSource
+
 /// Import a reference to a type definition, given an AbstractIL ILTypeRef, with caching
 val internal ImportILTypeRef: ImportMap -> range -> ILTypeRef -> TyconRef
 
@@ -79,7 +99,13 @@ val internal ImportProvidedMethodBaseAsILMethodRef: ImportMap -> range -> Tainte
 
 /// Import a set of Abstract IL generic parameter specifications as a list of new F# generic parameters.
 val internal ImportILGenericParameters:
-    (unit -> ImportMap) -> range -> ILScopeRef -> TType list -> ILGenericParameterDef list -> Typar list
+    (unit -> ImportMap) ->
+    range ->
+    ILScopeRef ->
+    TType list ->
+    Nullness.NullableContextSource ->
+    ILGenericParameterDef list ->
+        Typar list
 
 /// Import an IL assembly as a new TAST CCU
 val internal ImportILAssembly:
@@ -100,7 +126,19 @@ val internal ImportILAssemblyTypeForwarders:
 
 /// Import an IL type as an F# type, first rescoping to view the metadata from the current assembly
 /// being compiled. importInst gives the context for interpreting type variables.
-val RescopeAndImportILType:
+/// This function fully skips the 'nullness checking' metadata flags.
+val RescopeAndImportILTypeSkipNullness:
     scoref: ILScopeRef -> amap: ImportMap -> m: range -> importInst: TType list -> ilTy: ILType -> TType
 
+/// Import an IL type as an F# type, first rescoping to view the metadata from the current assembly
+/// being compiled. importInst gives the context for interpreting type variables.
+val RescopeAndImportILType:
+    scoref: ILScopeRef ->
+    amap: ImportMap ->
+    m: range ->
+    importInst: TType list ->
+    nullnessSource: Nullness.NullableAttributesSource ->
+    ilTy: ILType ->
+        TType
+
 val CanRescopeAndImportILType: scoref: ILScopeRef -> amap: ImportMap -> m: range -> ilTy: ILType -> bool
diff --git a/src/Compiler/Checking/infos.fs b/src/Compiler/Checking/infos.fs
index 8e88a4b80c8..022a0c6e4c9 100644
--- a/src/Compiler/Checking/infos.fs
+++ b/src/Compiler/Checking/infos.fs
@@ -9,6 +9,7 @@ open FSharp.Compiler
 open FSharp.Compiler.AbstractIL.IL
 open FSharp.Compiler.DiagnosticsLogger
 open FSharp.Compiler.Import
+open FSharp.Compiler.Import.Nullness
 open FSharp.Compiler.Syntax
 open FSharp.Compiler.SyntaxTreeOps
 open FSharp.Compiler.TcGlobals
@@ -216,7 +217,8 @@ type OptionalArgInfo =
                             else MissingValue
                     else
                         DefaultValue
-                CallerSide (analyze (ImportILTypeFromMetadata amap m ilScope ilTypeInst [] ilParam.Type))
+                                    // See above - the typpe is imported only in order to be analyzed for optional default value, nullness is irrelevant here.
+                CallerSide (analyze (ImportILTypeFromMetadataSkipNullness amap m ilScope ilTypeInst [] ilParam.Type))
             | Some v ->
                 CallerSide (Constant v)
         else
@@ -447,6 +449,10 @@ type ILTypeInfo =
         let (ILTypeInfo(g, ty, tref, tdef)) = x
         ILTypeInfo(g, instType inst ty, tref, tdef)
 
+    member x.NullableAttributes = AttributesFromIL(x.RawMetadata.MetadataIndex,x.RawMetadata.CustomAttrsStored)
+
+    member x.NullableClassSource = FromClass(x.NullableAttributes)
+
     static member FromType g ty =
         if isAnyTupleTy g ty then
             // When getting .NET metadata for the properties and methods
@@ -463,7 +469,17 @@ type ILTypeInfo =
             let tref = mkRefForNestedILTypeDef scoref (enc, tdef)
             ILTypeInfo(g, ty, tref, tdef)
         else
-            failwith "ILTypeInfo.FromType - no IL metadata for type"
+            failwith ("ILTypeInfo.FromType - no IL metadata for type" + System.Environment.StackTrace)
+
+[]
+type ILMethParentTypeInfo =
+    | IlType of ILTypeInfo
+    | CSharpStyleExtension of declaring:TyconRef * apparent:TType
+    
+    member x.ToType =
+        match x with
+        | IlType x -> x.ToType
+        | CSharpStyleExtension(apparent=x) -> x
 
 /// Describes an F# use of an IL method.
 []
@@ -472,32 +488,38 @@ type ILMethInfo =
     ///
     /// If ilDeclaringTyconRefOpt is 'Some' then this is an F# use of an C#-style extension method.
     /// If ilDeclaringTyconRefOpt is 'None' then ilApparentType is an IL type definition.
-    | ILMethInfo of g: TcGlobals * ilApparentType: TType * ilDeclaringTyconRefOpt: TyconRef option  * ilMethodDef: ILMethodDef * ilGenericMethodTyArgs: Typars
+    | ILMethInfo of g: TcGlobals * ilType:ILMethParentTypeInfo * ilMethodDef: ILMethodDef * ilGenericMethodTyArgs: Typars
 
-    member x.TcGlobals = match x with ILMethInfo(g, _, _, _, _) -> g
+    member x.TcGlobals = match x with ILMethInfo(g, _, _, _) -> g
 
     /// Get the apparent declaring type of the method as an F# type.
     /// If this is a C#-style extension method then this is the type which the method
     /// appears to extend. This may be a variable type.
-    member x.ApparentEnclosingType = match x with ILMethInfo(_, ty, _, _, _) -> ty
+    member x.ApparentEnclosingType = match x with ILMethInfo(_, ty, _, _) -> ty.ToType
 
     /// Like ApparentEnclosingType but use the compiled nominal type if this is a method on a tuple type
     member x.ApparentEnclosingAppType = convertToTypeWithMetadataIfPossible x.TcGlobals x.ApparentEnclosingType
 
     /// Get the declaring type associated with an extension member, if any.
-    member x.ILExtensionMethodDeclaringTyconRef = match x with ILMethInfo(_, _, tcrefOpt, _, _) -> tcrefOpt
+    member x.ILExtensionMethodDeclaringTyconRef = 
+        match x with
+        | ILMethInfo(ilType=CSharpStyleExtension(declaring= x)) -> Some x
+        | _ -> None
 
     /// Get the Abstract IL metadata associated with the method.
-    member x.RawMetadata = match x with ILMethInfo(_, _, _, md, _) -> md
+    member x.RawMetadata = match x with ILMethInfo(_, _, md, _) -> md
 
     /// Get the formal method type parameters associated with a method.
-    member x.FormalMethodTypars = match x with ILMethInfo(_, _, _, _, fmtps) -> fmtps
+    member x.FormalMethodTypars = match x with ILMethInfo(_, _, _, fmtps) -> fmtps
 
     /// Get the IL name of the method
     member x.ILName       = x.RawMetadata.Name
 
     /// Indicates if the method is an extension method
-    member x.IsILExtensionMethod = x.ILExtensionMethodDeclaringTyconRef.IsSome
+    member x.IsILExtensionMethod = 
+        match x with
+        | ILMethInfo(ilType=CSharpStyleExtension _) -> true
+        | _ -> false
 
     /// Get the declaring type of the method. If this is an C#-style extension method then this is the IL type
     /// holding the static member that is the extension method.
@@ -558,15 +580,28 @@ type ILMethInfo =
     /// Does it appear to the user as an instance method?
     member x.IsInstance = not x.IsConstructor &&  not x.IsStatic
 
+    member x.NullableFallback = 
+        let raw = x.RawMetadata
+        let classAttrs = 
+            match x with
+            | ILMethInfo(ilType=CSharpStyleExtension(declaring= t)) when t.IsILTycon -> AttributesFromIL(t.ILTyconRawMetadata.MetadataIndex,t.ILTyconRawMetadata.CustomAttrsStored)
+            // C#-style extension defined in F# -> we do not support manually adding NullableContextAttribute by F# users.
+            | ILMethInfo(ilType=CSharpStyleExtension _)  -> AttributesFromIL(0,Given(ILAttributes.Empty))
+            | ILMethInfo(ilType=IlType(t)) -> t.NullableAttributes
+
+        FromMethodAndClass(AttributesFromIL(raw.MetadataIndex,raw.CustomAttrsStored),classAttrs)
+
+    member x.GetNullness(p:ILParameter) = {DirectAttributes = AttributesFromIL(p.MetadataIndex,p.CustomAttrsStored); Fallback = x.NullableFallback}
+
     /// Get the argument types of the the IL method. If this is an C#-style extension method
     /// then drop the object argument.
     member x.GetParamTypes(amap, m, minst) =
-        x.ParamMetadata |> List.map (fun p -> ImportParameterTypeFromMetadata amap m p.Type (fun _ -> p.CustomAttrs) x.MetadataScope x.DeclaringTypeInst minst)
+        x.ParamMetadata |> List.map (fun p -> ImportParameterTypeFromMetadata amap m (x.GetNullness(p)) p.Type x.MetadataScope x.DeclaringTypeInst minst)
 
     /// Get all the argument types of the IL method. Include the object argument even if this is
     /// an C#-style extension method.
     member x.GetRawArgTypes(amap, m, minst) =
-        x.RawMetadata.Parameters |> List.map (fun p -> ImportParameterTypeFromMetadata amap m p.Type (fun _ -> p.CustomAttrs) x.MetadataScope x.DeclaringTypeInst minst)
+        x.RawMetadata.Parameters |> List.map (fun p -> ImportParameterTypeFromMetadata amap m (x.GetNullness(p)) p.Type x.MetadataScope x.DeclaringTypeInst minst)
 
     /// Get info about the arguments of the IL method. If this is an C#-style extension method then
     /// drop the object argument.
@@ -575,7 +610,7 @@ type ILMethInfo =
     member x.GetParamNamesAndTypes(amap, m, minst) =
         let scope = x.MetadataScope
         let tinst = x.DeclaringTypeInst
-        x.ParamMetadata |> List.map (fun p -> ParamNameAndType(Option.map (mkSynId m) p.Name, ImportParameterTypeFromMetadata amap m p.Type (fun _ -> p.CustomAttrs) scope tinst minst) )
+        x.ParamMetadata |> List.map (fun p -> ParamNameAndType(Option.map (mkSynId m) p.Name, ImportParameterTypeFromMetadata amap m (x.GetNullness(p))  p.Type scope tinst minst) )
 
     /// Get a reference to the method (dropping all generic instantiations), as an Abstract IL ILMethodRef.
     member x.ILMethodRef =
@@ -599,12 +634,13 @@ type ILMethInfo =
 
     /// Get the (zero or one) 'self'/'this'/'object' arguments associated with an IL method.
     /// An instance extension method returns one object argument.
-    member x.GetObjArgTypes(amap, m, minst) =
+    member x.GetObjArgTypes(amap, m, minst) =    
         // All C#-style extension methods are instance. We have to re-read the 'obj' type w.r.t. the
         // method instantiation.
         if x.IsILExtensionMethod then
             let p = x.RawMetadata.Parameters.Head
-            [ ImportParameterTypeFromMetadata amap m p.Type (fun _ -> p.CustomAttrs) x.MetadataScope x.DeclaringTypeInst minst ]
+            let nullableSource = {DirectAttributes = AttributesFromIL(p.MetadataIndex,p.CustomAttrsStored); Fallback = x.NullableFallback}
+            [ ImportParameterTypeFromMetadata amap m nullableSource p.Type x.MetadataScope x.DeclaringTypeInst minst ]
         else if x.IsInstance then
             [ x.ApparentEnclosingType ]
         else
@@ -612,10 +648,12 @@ type ILMethInfo =
 
     /// Get the compiled return type of the method, where 'void' is None.
     member x.GetCompiledReturnType (amap, m, minst) =
-        ImportReturnTypeFromMetadata amap m x.RawMetadata.Return.Type (fun _ -> x.RawMetadata.Return.CustomAttrs) x.MetadataScope x.DeclaringTypeInst minst
+        let ilReturn = x.RawMetadata.Return
+        let nullableSource = {DirectAttributes = AttributesFromIL(ilReturn.MetadataIndex,ilReturn.CustomAttrsStored); Fallback = x.NullableFallback}
+        ImportReturnTypeFromMetadata amap m nullableSource ilReturn.Type x.MetadataScope x.DeclaringTypeInst minst
 
     /// Get the F# view of the return type of the method, where 'void' is 'unit'.
-    member x.GetFSharpReturnType (amap, m, minst) =
+    member x.GetFSharpReturnType (amap, m, minst) =      
         x.GetCompiledReturnType(amap, m, minst)
         |> GetFSharpViewOfReturnType amap.g
 
@@ -1040,14 +1078,19 @@ type MethInfo =
     /// Build IL method infos.
     static member CreateILMeth (amap: ImportMap, m, ty: TType, md: ILMethodDef) =
         let tinfo = ILTypeInfo.FromType amap.g ty
-        let mtps = ImportILGenericParameters (fun () -> amap) m tinfo.ILScopeRef tinfo.TypeInstOfRawMetadata md.GenericParams
-        ILMeth (amap.g, ILMethInfo(amap.g, ty, None, md, mtps), None)
+        let nullableFallback = FromMethodAndClass(AttributesFromIL(md.MetadataIndex,md.CustomAttrsStored),tinfo.NullableAttributes)
+        let mtps = ImportILGenericParameters (fun () -> amap) m tinfo.ILScopeRef tinfo.TypeInstOfRawMetadata nullableFallback md.GenericParams
+        ILMeth (amap.g, ILMethInfo(amap.g, IlType tinfo, md, mtps), None)
 
     /// Build IL method infos for a C#-style extension method
-    static member CreateILExtensionMeth (amap, m, apparentTy: TType, declaringTyconRef: TyconRef, extMethPri, md: ILMethodDef) =
+    static member CreateILExtensionMeth (amap:ImportMap, m, apparentTy: TType, declaringTyconRef: TyconRef, extMethPri, md: ILMethodDef) =
         let scoref =  declaringTyconRef.CompiledRepresentationForNamedType.Scope
-        let mtps = ImportILGenericParameters (fun () -> amap) m scoref [] md.GenericParams
-        ILMeth (amap.g, ILMethInfo(amap.g, apparentTy, Some declaringTyconRef, md, mtps), extMethPri)
+        let typeInfo = CSharpStyleExtension(declaringTyconRef,apparentTy)
+        let declaringMetadata = declaringTyconRef.ILTyconRawMetadata
+        let declaringAttributes = AttributesFromIL(declaringMetadata.MetadataIndex,declaringMetadata.CustomAttrsStored)
+        let nullableFallback = FromMethodAndClass(AttributesFromIL(md.MetadataIndex,md.CustomAttrsStored),declaringAttributes)
+        let mtps = ImportILGenericParameters (fun () -> amap) m scoref [] nullableFallback md.GenericParams
+        ILMeth (amap.g, ILMethInfo(amap.g, typeInfo, md, mtps), extMethPri)
 
     /// Tests whether two method infos have the same underlying definition.
     /// Used to merge operator overloads collected from left and right of an operator constraint.
@@ -1078,8 +1121,8 @@ type MethInfo =
         match x with
         | ILMeth(_g, ilminfo, pri) ->
             match ilminfo with
-            | ILMethInfo(_, ty, None, md, _) -> MethInfo.CreateILMeth(amap, m, instType inst ty, md)
-            | ILMethInfo(_, ty, Some declaringTyconRef, md, _) -> MethInfo.CreateILExtensionMeth(amap, m, instType inst ty, declaringTyconRef, pri, md)
+            | ILMethInfo(_, IlType ty, md, _) -> MethInfo.CreateILMeth(amap, m, instType inst ty.ToType, md)
+            | ILMethInfo(_, CSharpStyleExtension(declaringTyconRef,ty), md, _) -> MethInfo.CreateILExtensionMeth(amap, m, instType inst ty, declaringTyconRef, pri, md)
         | FSMeth(g, ty, vref, pri) -> FSMeth(g, instType inst ty, vref, pri)
         | DefaultStructCtor(g, ty) -> DefaultStructCtor(g, instType inst ty)
 #if !NO_TYPEPROVIDERS
@@ -1269,12 +1312,17 @@ type MethInfo =
 
             let formalRetTy, formalParams =
                 match x with
-                | ILMeth(_, ilminfo, _) ->
+                | ILMeth(_, ilminfo, _) ->                
                     let ftinfo = ILTypeInfo.FromType g (TType_app(tcref, formalEnclosingTyparTys, g.knownWithoutNull))
-                    let formalRetTy = ImportReturnTypeFromMetadata amap m ilminfo.RawMetadata.Return.Type (fun _ -> ilminfo.RawMetadata.Return.CustomAttrs) ftinfo.ILScopeRef ftinfo.TypeInstOfRawMetadata formalMethTyparTys
+
+                    let ilReturn = ilminfo.RawMetadata.Return
+                    let nullableSource = {DirectAttributes = AttributesFromIL(ilReturn.MetadataIndex,ilReturn.CustomAttrsStored); Fallback = ilminfo.NullableFallback}
+
+                    let formalRetTy = ImportReturnTypeFromMetadata amap m nullableSource ilReturn.Type ftinfo.ILScopeRef ftinfo.TypeInstOfRawMetadata formalMethTyparTys
                     let formalParams =
                         [ [ for p in ilminfo.RawMetadata.Parameters do
-                                let paramTy = ImportILTypeFromMetadataWithAttributes amap m ftinfo.ILScopeRef ftinfo.TypeInstOfRawMetadata formalMethTyparTys p.Type (fun _ -> p.CustomAttrs)
+                                let nullableSource = {nullableSource with DirectAttributes = AttributesFromIL(p.MetadataIndex,p.CustomAttrsStored)}
+                                let paramTy = ImportILTypeFromMetadataWithAttributes amap m ftinfo.ILScopeRef ftinfo.TypeInstOfRawMetadata formalMethTyparTys nullableSource p.Type
                                 yield TSlotParam(p.Name, paramTy, p.IsIn, p.IsOut, p.IsOptional, []) ] ]
                     formalRetTy, formalParams
 #if !NO_TYPEPROVIDERS
@@ -1472,8 +1520,10 @@ type ILFieldInfo =
 
      /// Get the type of the field as an F# type
     member x.FieldType(amap, m) =
-        match x with
-        | ILFieldInfo (tinfo, fdef) -> ImportILTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInstOfRawMetadata [] fdef.FieldType
+        match x with     
+        | ILFieldInfo (tinfo, fdef) -> 
+            let nullness = {DirectAttributes = AttributesFromIL(fdef.MetadataIndex,fdef.CustomAttrsStored); Fallback = tinfo.NullableClassSource}
+            ImportILTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInstOfRawMetadata [] nullness fdef.FieldType
 #if !NO_TYPEPROVIDERS
         | ProvidedField(amap, fi, m) -> ImportProvidedType amap m (fi.PApply((fun fi -> fi.FieldType), m))
 #endif
@@ -1608,13 +1658,13 @@ type ILPropInfo =
     member x.GetterMethod =
         assert x.HasGetter
         let mdef = resolveILMethodRef x.ILTypeInfo.RawMetadata x.RawMetadata.GetMethod.Value
-        ILMethInfo(x.TcGlobals, x.ILTypeInfo.ToType, None, mdef, [])
+        ILMethInfo(x.TcGlobals, IlType x.ILTypeInfo, mdef, [])
 
     /// Gets the ILMethInfo of the 'set' method for the IL property
     member x.SetterMethod =
         assert x.HasSetter
         let mdef = resolveILMethodRef x.ILTypeInfo.RawMetadata x.RawMetadata.SetMethod.Value
-        ILMethInfo(x.TcGlobals, x.ILTypeInfo.ToType, None, mdef, [])
+        ILMethInfo(x.TcGlobals, IlType x.ILTypeInfo, mdef, [])
 
     /// Indicates if the IL property has a 'get' method
     member x.HasGetter = Option.isSome x.RawMetadata.GetMethod
@@ -1647,21 +1697,34 @@ type ILPropInfo =
     /// Any type parameters of the enclosing type are instantiated in the type returned.
     member x.GetParamNamesAndTypes(amap, m) =
         let (ILPropInfo (tinfo, pdef)) = x
-        pdef.Args |> List.map (fun ty -> ParamNameAndType(None, ImportILTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInstOfRawMetadata [] ty) )
+        if x.HasGetter then
+            x.GetterMethod.GetParamNamesAndTypes(amap,m,tinfo.TypeInstOfRawMetadata)
+        else if x.HasSetter then
+            x.SetterMethod.GetParamNamesAndTypes(amap,m,tinfo.TypeInstOfRawMetadata)
+        else
+            // Fallback-only for invalid properties
+            pdef.Args |> List.map (fun ty -> ParamNameAndType(None, ImportILTypeFromMetadataSkipNullness amap m tinfo.ILScopeRef tinfo.TypeInstOfRawMetadata [] ty) )
 
     /// Get the types of the indexer arguments associated with the IL property.
     ///
     /// Any type parameters of the enclosing type are instantiated in the type returned.
     member x.GetParamTypes(amap, m) =
         let (ILPropInfo (tinfo, pdef)) = x
-        pdef.Args |> List.map (fun ty -> ImportILTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInstOfRawMetadata [] ty)
+        if x.HasGetter then
+            x.GetterMethod.GetParamTypes(amap,m,tinfo.TypeInstOfRawMetadata)
+        else if x.HasSetter then
+            x.SetterMethod.GetParamTypes(amap,m,tinfo.TypeInstOfRawMetadata)
+        else
+            // Fallback-only for invalid properties
+            pdef.Args |> List.map (fun ty -> ImportILTypeFromMetadataSkipNullness amap m tinfo.ILScopeRef tinfo.TypeInstOfRawMetadata [] ty)
 
     /// Get the return type of the IL property.
     ///
     /// Any type parameters of the enclosing type are instantiated in the type returned.
     member x.GetPropertyType (amap, m) =
         let (ILPropInfo (tinfo, pdef)) = x
-        ImportILTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInstOfRawMetadata [] pdef.PropertyType
+        let nullness = {DirectAttributes = AttributesFromIL(pdef.MetadataIndex,pdef.CustomAttrsStored); Fallback = tinfo.NullableClassSource}
+        ImportILTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInstOfRawMetadata [] nullness pdef.PropertyType
 
     override x.ToString() = x.ILTypeInfo.ToString() + "::" + x.PropertyName
 
@@ -1939,7 +2002,7 @@ type PropInfo =
 
     /// Get the result type of the property
     member x.GetPropertyType (amap, m) =
-        match x with
+        match x with      
         | ILProp ilpinfo -> ilpinfo.GetPropertyType (amap, m)
         | FSProp (g, _, Some vref, _)
         | FSProp (g, _, _, Some vref) ->
@@ -1957,7 +2020,7 @@ type PropInfo =
     ///
     /// If the property is in a generic type, then the type parameters are instantiated in the types returned.
     member x.GetParamNamesAndTypes(amap, m) =
-        match x with
+        match x with     
         | ILProp ilpinfo -> ilpinfo.GetParamNamesAndTypes(amap, m)
         | FSProp (g, ty, Some vref, _)
         | FSProp (g, ty, _, Some vref) ->
@@ -1978,7 +2041,7 @@ type PropInfo =
         |> List.map (fun (ParamNameAndType(nmOpt, paramTy)) -> ParamData(false, false, false, NotOptional, NoCallerInfo, nmOpt, ReflectedArgInfo.None, paramTy))
 
     /// Get the types of the indexer parameters associated with the property
-    member x.GetParamTypes(amap, m) =
+    member x.GetParamTypes(amap, m) =  
       x.GetParamNamesAndTypes(amap, m) |> List.map (fun (ParamNameAndType(_, ty)) -> ty)
 
     /// Get a MethInfo for the 'getter' method associated with the property
@@ -2073,12 +2136,12 @@ type ILEventInfo =
     /// Get the ILMethInfo describing the 'add' method associated with the event
     member x.AddMethod =
         let mdef = resolveILMethodRef x.ILTypeInfo.RawMetadata x.RawMetadata.AddMethod
-        ILMethInfo(x.TcGlobals, x.ILTypeInfo.ToType, None, mdef, [])
+        ILMethInfo(x.TcGlobals, IlType x.ILTypeInfo, mdef, [])
 
     /// Get the ILMethInfo describing the 'remove' method associated with the event
     member x.RemoveMethod =
         let mdef = resolveILMethodRef x.ILTypeInfo.RawMetadata x.RawMetadata.RemoveMethod
-        ILMethInfo(x.TcGlobals, x.ILTypeInfo.ToType, None, mdef, [])
+        ILMethInfo(x.TcGlobals, IlType x.ILTypeInfo, mdef, [])
 
     /// Get the declaring type of the event as an ILTypeRef
     member x.TypeRef = x.ILTypeInfo.ILTypeRef
@@ -2274,9 +2337,10 @@ type EventInfo =
         match x with
         | ILEvent(ILEventInfo(tinfo, edef)) ->
             // Get the delegate type associated with an IL event, taking into account the instantiation of the
-            // declaring type.
+            // declaring type
             if Option.isNone edef.EventType then error (nonStandardEventError x.EventName m)
-            ImportILTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInstOfRawMetadata [] edef.EventType.Value
+            let nullness = {DirectAttributes = AttributesFromIL(edef.MetadataIndex,edef.CustomAttrsStored); Fallback = tinfo.NullableClassSource}
+            ImportILTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInstOfRawMetadata [] nullness edef.EventType.Value
 
         | FSEvent(g, p, _, _) ->
             FindDelegateTypeOfPropertyEvent g amap x.EventName m (p.GetPropertyType(amap, m))
diff --git a/src/Compiler/Checking/infos.fsi b/src/Compiler/Checking/infos.fsi
index 7e1ee813ca8..41998e5253c 100644
--- a/src/Compiler/Checking/infos.fsi
+++ b/src/Compiler/Checking/infos.fsi
@@ -178,13 +178,19 @@ type ILTypeInfo =
 
     member TypeInstOfRawMetadata: TypeInst
 
+[]
+type ILMethParentTypeInfo =
+    | IlType of ILTypeInfo
+    | CSharpStyleExtension of declaring: TyconRef * apparent: TType
+
+    member ToType: TType
+
 /// Describes an F# use of an IL method.
 []
 type ILMethInfo =
     | ILMethInfo of
         g: TcGlobals *
-        ilApparentType: TType *
-        ilDeclaringTyconRefOpt: TyconRef option *
+        ilType: ILMethParentTypeInfo *
         ilMethodDef: ILMethodDef *
         ilGenericMethodTyArgs: Typars
 
diff --git a/src/Compiler/CodeGen/EraseUnions.fs b/src/Compiler/CodeGen/EraseUnions.fs
index e3679a39020..c500f8ae511 100644
--- a/src/Compiler/CodeGen/EraseUnions.fs
+++ b/src/Compiler/CodeGen/EraseUnions.fs
@@ -871,12 +871,7 @@ let convAlternativeDef
         | SpecialFSharpListHelpers ->
 
             let baseTesterMeths, baseTesterProps =
-                if
-                    g.langVersion.SupportsFeature LanguageFeature.UnionIsPropertiesVisible
-                    && cud.HasHelpers = AllHelpers
-                then
-                    [], []
-                elif cud.UnionCases.Length <= 1 then
+                if cud.UnionCases.Length <= 1 then
                     [], []
                 elif repr.RepresentOneAlternativeAsNull info then
                     [], []
diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs
index 1f331c30987..6680057750a 100644
--- a/src/Compiler/CodeGen/IlxGen.fs
+++ b/src/Compiler/CodeGen/IlxGen.fs
@@ -10731,6 +10731,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) =
                         else
                             ILTypeDefKind.Class
                     | TFSharpClass -> ILTypeDefKind.Class
+
                     | TFSharpStruct -> ILTypeDefKind.ValueType
                     | TFSharpInterface -> ILTypeDefKind.Interface
                     | TFSharpEnum -> ILTypeDefKind.Enum
@@ -11414,19 +11415,24 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) =
                     // private static field for lists etc.
                     //
                     // Also discard the F#-compiler supplied implementation of the Empty, IsEmpty, Value and None properties.
+
                     let tdefDiscards =
                         Some(
                             (fun (md: ILMethodDef) ->
                                 (cuinfo.HasHelpers = SpecialFSharpListHelpers
                                  && (md.Name = "get_Empty" || md.Name = "Cons" || md.Name = "get_IsEmpty"))
                                 || (cuinfo.HasHelpers = SpecialFSharpOptionHelpers
-                                    && (md.Name = "get_Value" || md.Name = "get_None" || md.Name = "Some"))),
+                                    && (md.Name = "get_Value" || md.Name = "get_None" || md.Name = "Some"))
+                                || (cuinfo.HasHelpers = AllHelpers
+                                    && (md.Name.StartsWith("get_Is") && not (tdef2.Methods.FindByName(md.Name).IsEmpty)))),
 
                             (fun (pd: ILPropertyDef) ->
                                 (cuinfo.HasHelpers = SpecialFSharpListHelpers
                                  && (pd.Name = "Empty" || pd.Name = "IsEmpty"))
                                 || (cuinfo.HasHelpers = SpecialFSharpOptionHelpers
-                                    && (pd.Name = "Value" || pd.Name = "None")))
+                                    && (pd.Name = "Value" || pd.Name = "None"))
+                                || (cuinfo.HasHelpers = AllHelpers
+                                    && (pd.Name.StartsWith("Is") && not (tdef2.Properties.LookupByName(pd.Name).IsEmpty))))
                         )
 
                     tdef2, tdefDiscards
diff --git a/src/Compiler/Symbols/Exprs.fs b/src/Compiler/Symbols/Exprs.fs
index 3aa8f1cbe5e..5ad053b2d9f 100644
--- a/src/Compiler/Symbols/Exprs.fs
+++ b/src/Compiler/Symbols/Exprs.fs
@@ -1149,9 +1149,12 @@ module FSharpExprConvert =
                 // TODO: this will not work for curried methods in F# classes.
                 // This is difficult to solve as the information in the ILMethodRef
                 // is not sufficient to resolve to a symbol unambiguously in these cases.
-                let argTys = [ ilMethRef.ArgTypes |> List.map (ImportILTypeFromMetadata cenv.amap m scoref tinst1 tinst2) ]
+
+                                                              // If this was an ILTycon with potential nullness, try1 is Some(..) and this branch not hit
+                let argTys = [ ilMethRef.ArgTypes |> List.map (ImportILTypeFromMetadataSkipNullness cenv.amap m scoref tinst1 tinst2) ]
                 let retTy = 
-                    match ImportReturnTypeFromMetadata cenv.amap m ilMethRef.ReturnType (fun _ -> emptyILCustomAttrs) scoref tinst1 tinst2 with 
+                    let nullableAttributes = Import.Nullness.NullableAttributesSource.Empty
+                    match ImportReturnTypeFromMetadata cenv.amap m nullableAttributes ilMethRef.ReturnType scoref tinst1 tinst2 with 
                     | None -> if isCtor then enclosingTy else g.unit_ty
                     | Some ty -> ty
 
diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs
index 921edde3562..152ab480dfd 100644
--- a/src/Compiler/TypedTree/TcGlobals.fs
+++ b/src/Compiler/TypedTree/TcGlobals.fs
@@ -1468,6 +1468,8 @@ type TcGlobals(
   member val attrib_IsReadOnlyAttribute = findOrEmbedSysPublicType "System.Runtime.CompilerServices.IsReadOnlyAttribute"
   member val attrib_IsUnmanagedAttribute = findOrEmbedSysPublicType "System.Runtime.CompilerServices.IsUnmanagedAttribute"
   member val attrib_DynamicDependencyAttribute = findOrEmbedSysPublicType "System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute"
+  member val attrib_NullableAttribute_opt = tryFindSysAttrib "System.Runtime.CompilerServices.NullableAttribute"
+  member val attrib_NullableContextAttribute_opt = tryFindSysAttrib "System.Runtime.CompilerServices.NullableContextAttribute"
   member val attrib_NullableAttribute = findOrEmbedSysPublicType "System.Runtime.CompilerServices.NullableAttribute"
   member val attrib_NullableContextAttribute = findOrEmbedSysPublicType "System.Runtime.CompilerServices.NullableContextAttribute"
   member val attrib_MemberNotNullWhenAttribute  = findOrEmbedSysPublicType "System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute"
diff --git a/src/Compiler/TypedTree/TypedTree.fs b/src/Compiler/TypedTree/TypedTree.fs
index 11351308987..5e7c01094d9 100644
--- a/src/Compiler/TypedTree/TypedTree.fs
+++ b/src/Compiler/TypedTree/TypedTree.fs
@@ -4210,7 +4210,7 @@ type RecdFieldRef =
 
     override x.ToString() = x.FieldName
 
-[]
+[]
 type Nullness = 
    | Known of NullnessInfo
    | Variable of NullnessVar
@@ -4228,6 +4228,7 @@ type Nullness =
    override n.ToString() = match n.Evaluate() with NullnessInfo.WithNull -> "?"  | NullnessInfo.WithoutNull -> "" | NullnessInfo.AmbivalentToNull -> "%"
 
 // Note, nullness variables are only created if the nullness checking feature is on
+[]
 type NullnessVar() = 
     let mutable solution: Nullness option = None
 
diff --git a/src/Compiler/TypedTree/TypedTree.fsi b/src/Compiler/TypedTree/TypedTree.fsi
index 1d606257b9a..19a815daff9 100644
--- a/src/Compiler/TypedTree/TypedTree.fsi
+++ b/src/Compiler/TypedTree/TypedTree.fsi
@@ -3034,7 +3034,7 @@ type NullnessInfo =
     /// we know we don't care
     | AmbivalentToNull
 
-[]
+[]
 type Nullness =
     | Known of NullnessInfo
     | Variable of NullnessVar
@@ -3043,6 +3043,7 @@ type Nullness =
 
     member TryEvaluate: unit -> NullnessInfo voption
 
+[]
 type NullnessVar =
     new: unit -> NullnessVar
     member Evaluate: unit -> NullnessInfo
diff --git a/src/Compiler/TypedTree/TypedTreeBasics.fs b/src/Compiler/TypedTree/TypedTreeBasics.fs
index 04052291cb1..f716ea69914 100644
--- a/src/Compiler/TypedTree/TypedTreeBasics.fs
+++ b/src/Compiler/TypedTree/TypedTreeBasics.fs
@@ -252,20 +252,31 @@ let combineNullness (nullnessOrig: Nullness) (nullnessNew: Nullness) =
         | NullnessInfo.AmbivalentToNull -> nullnessNew
         | NullnessInfo.WithNull -> nullnessOrig
 
+let nullnessEquiv (nullnessOrig: Nullness) (nullnessNew: Nullness) = LanguagePrimitives.PhysicalEquality nullnessOrig nullnessNew
+
 let tryAddNullnessToTy nullnessNew (ty:TType) = 
     match ty with
     | TType_var (tp, nullnessOrig) -> 
-        // TODO NULLNESS: make this avoid allocation if no change
-        Some (TType_var (tp, combineNullness nullnessOrig nullnessNew))
+        let nullnessAfter = combineNullness nullnessOrig nullnessNew
+        if nullnessEquiv nullnessAfter nullnessOrig then
+            Some ty
+        else 
+            Some (TType_var (tp, nullnessAfter))
     | TType_app (tcr, tinst, nullnessOrig) -> 
-        // TODO NULLNESS: make this avoid allocation if no change
-        Some (TType_app (tcr, tinst, combineNullness nullnessOrig nullnessNew))
+        let nullnessAfter = combineNullness nullnessOrig nullnessNew
+        if nullnessEquiv nullnessAfter nullnessOrig then
+            Some ty
+        else 
+            Some (TType_app (tcr, tinst, nullnessAfter))
     | TType_ucase _ -> None // TODO NULLNESS
     | TType_tuple _ -> None // TODO NULLNESS
     | TType_anon _ -> None // TODO NULLNESS
     | TType_fun (d, r, nullnessOrig) ->
-        // TODO NULLNESS: make this avoid allocation if no change
-        Some (TType_fun (d, r, combineNullness nullnessOrig nullnessNew))
+        let nullnessAfter = combineNullness nullnessOrig nullnessNew
+        if nullnessEquiv nullnessAfter nullnessOrig then
+            Some ty
+        else 
+            Some (TType_fun (d, r, nullnessAfter))
     | TType_forall _ -> None
     | TType_measure _ -> None
 
diff --git a/src/Compiler/Utilities/Activity.fs b/src/Compiler/Utilities/Activity.fs
index 79697eae494..22405544e2f 100644
--- a/src/Compiler/Utilities/Activity.fs
+++ b/src/Compiler/Utilities/Activity.fs
@@ -54,20 +54,21 @@ module internal Activity =
     module Events =
         let cacheHit = "cacheHit"
 
-    type System.Diagnostics.Activity with
+    type Diagnostics.Activity with
 
         member this.RootId =
             let rec rootID (act: Activity) =
-                if isNull act.ParentId then act.Id else rootID act.Parent
+                match act.Parent with
+                | NonNull parent -> rootID parent
+                | Null -> act.Id
 
             rootID this
 
         member this.Depth =
             let rec depth (act: Activity) acc =
-                if isNull act.ParentId then
-                    acc
-                else
-                    depth act.Parent (acc + 1)
+                match act.Parent with
+                | NonNull parent -> depth parent (acc + 1)
+                | Null -> acc
 
             depth this 0
 
@@ -77,8 +78,8 @@ module internal Activity =
         let activity = activitySource.CreateActivity(name, ActivityKind.Internal)
 
         match activity with
-        | null -> activity
-        | activity ->
+        | Null -> activity
+        | NonNull activity ->
             for key, value in tags do
                 activity.AddTag(key, value) |> ignore
 
@@ -87,8 +88,9 @@ module internal Activity =
     let startNoTags (name: string) : IDisposable = activitySource.StartActivity name
 
     let addEvent name =
-        if (not (isNull Activity.Current)) && Activity.Current.Source = activitySource then
-            Activity.Current.AddEvent(ActivityEvent name) |> ignore
+        match Activity.Current with
+        | NonNull activity when activity.Source = activitySource -> activity.AddEvent(ActivityEvent name) |> ignore
+        | _ -> ()
 
     module Profiling =
 
diff --git a/src/Compiler/Utilities/illib.fs b/src/Compiler/Utilities/illib.fs
index dd2030d156b..6bf85595108 100644
--- a/src/Compiler/Utilities/illib.fs
+++ b/src/Compiler/Utilities/illib.fs
@@ -422,6 +422,9 @@ module Option =
         with _ ->
             None
 
+module internal ValueTuple = 
+    let inline map1Of2 ([]f) struct(a1, a2) = struct(f a1, a2)
+
 module List =
 
     let sortWithOrder (c: IComparer<'T>) elements =
@@ -648,6 +651,22 @@ module List =
         | Some x -> x :: l
         | _ -> l
 
+    
+    []
+    let rec private vMapFoldWithAcc<'T, 'State, 'Result> (mapping: 'State -> 'T -> struct('Result * 'State)) state list acc : struct('Result list * 'State) =
+        match list with
+        | [] -> acc, state
+        | [h] ->
+            mapping state h
+            |> ValueTuple.map1Of2 (fun x -> x::acc)
+        | h :: t ->
+            let struct(mappedHead, stateHead) = mapping state h
+            vMapFoldWithAcc mapping stateHead t (mappedHead :: acc)
+
+    let vMapFold<'T, 'State, 'Result> (mapping: 'State -> 'T -> struct('Result * 'State)) state list : struct('Result list * 'State) =
+        vMapFoldWithAcc mapping state list []
+        |> ValueTuple.map1Of2 List.rev
+
 module ResizeArray =
 
     /// Split a ResizeArray into an array of smaller chunks.
diff --git a/src/Compiler/Utilities/illib.fsi b/src/Compiler/Utilities/illib.fsi
index 1110e8134b1..266f884fa01 100644
--- a/src/Compiler/Utilities/illib.fsi
+++ b/src/Compiler/Utilities/illib.fsi
@@ -240,6 +240,8 @@ module internal List =
 
     val prependIfSome: x: 'a option -> l: 'a list -> 'a list
 
+    val vMapFold<'T,'State,'Result> : mapping:('State -> 'T -> struct('Result * 'State)) -> state:'State -> list:'T list -> struct('Result list * 'State)
+
 module internal ResizeArray =
 
     /// Split a ResizeArray into an array of smaller chunks.
diff --git a/src/FSharp.Core/prim-types.fs b/src/FSharp.Core/prim-types.fs
index e2b76c37dab..d44fa86610b 100644
--- a/src/FSharp.Core/prim-types.fs
+++ b/src/FSharp.Core/prim-types.fs
@@ -4294,6 +4294,12 @@ namespace Microsoft.FSharp.Core
             match value with 
             | null -> raise (new ArgumentNullException(argumentName))        
             | _ ->  (# "" value : 'T #)
+#else
+        []
+        let inline (|Null|NonNull|) (value : 'T) : Choice when 'T : null and 'T : not struct = 
+            match value with 
+            | null -> Null () 
+            | _ -> NonNull (# "" value : 'T #)
 #endif
 
         []
diff --git a/src/FSharp.Core/prim-types.fsi b/src/FSharp.Core/prim-types.fsi
index 5339a5a4d59..13fb9e46ff9 100644
--- a/src/FSharp.Core/prim-types.fsi
+++ b/src/FSharp.Core/prim-types.fsi
@@ -3476,6 +3476,13 @@ namespace Microsoft.FSharp.Core
         []
         []
         val inline isNullV : value:Nullable<'T> -> bool
+#else
+        /// Determines whether the given value is null.
+        /// The value to check.
+        /// A choice indicating whether the value is null or not-null.
+        []
+        []
+        val inline (|Null|NonNull|) : value: 'T -> Choice  when 'T : null and 'T : not struct 
 #endif
 
         /// Determines whether the given value is not null.
diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1
index 373cd534ce2..8d2d17adef2 100644
--- a/tests/AheadOfTime/Trimming/check.ps1
+++ b/tests/AheadOfTime/Trimming/check.ps1
@@ -40,7 +40,7 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) {
 # error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher.
 
 # Check net7.0 trimmed assemblies
-CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len 288256
+CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len 288768
 
 # Check net7.0 trimmed assemblies
 CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net8.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 8822272 
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericStructDu.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericStructDu.fs
new file mode 100644
index 00000000000..cf72987cafb
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericStructDu.fs
@@ -0,0 +1,11 @@
+module TestModule
+
+[]
+type MyStructOption<'T when 'T: not null> = 
+    | MyStructNone
+    | MyStructSome of nestedGenericField : list> * notNullField2 : string * canBeNullField : (string | null) * notNullField1 : 'T
+
+let mapStructContents f myOpt =
+    match myOpt with
+    | MyStructNone -> MyStructNone
+    | MyStructSome(ngf,s,ns,x) -> MyStructSome (ngf,s,ns,f x)
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericStructDu.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericStructDu.fs.il.net472.bsl
new file mode 100644
index 00000000000..97f43391f53
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericStructDu.fs.il.net472.bsl
@@ -0,0 +1,644 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed TestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .class sequential autochar serializable sealed nested public beforefieldinit MyStructOption`1
+         extends [runtime]System.ValueType
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                   61 79 28 29 2C 6E 71 7D 00 00 )                   
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
+    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type T 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .class abstract auto ansi sealed nested public Tags
+           extends [runtime]System.Object
+    {
+      .param type T 
+        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .field public static literal int32 MyStructNone = int32(0x00000000)
+      .field public static literal int32 MyStructSome = int32(0x00000001)
+    } 
+
+    .field assembly class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> _nestedGenericField
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly string _notNullField2
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly string _canBeNullField
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly !T _notNullField1
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly int32 _tag
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .method public static valuetype TestModule/MyStructOption`1 
+            get_MyStructNone() cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldc.i4.0
+      IL_0001:  newobj     instance void valuetype TestModule/MyStructOption`1::.ctor(int32)
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsMyStructNone() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
+      IL_0006:  ldc.i4.0
+      IL_0007:  ceq
+      IL_0009:  ret
+    } 
+
+    .method public static valuetype TestModule/MyStructOption`1 
+            NewMyStructSome(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> _nestedGenericField,
+                            string _notNullField2,
+                            string _canBeNullField,
+                            !T _notNullField1) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
+      .param [1]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
+      .param [3]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  5
+      .locals init (valuetype TestModule/MyStructOption`1 V_0)
+      IL_0000:  ldloca.s   V_0
+      IL_0002:  initobj    valuetype TestModule/MyStructOption`1
+      IL_0008:  ldloca.s   V_0
+      IL_000a:  ldc.i4.1
+      IL_000b:  stfld      int32 valuetype TestModule/MyStructOption`1::_tag
+      IL_0010:  ldloca.s   V_0
+      IL_0012:  ldarg.0
+      IL_0013:  stfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
+      IL_0018:  ldloca.s   V_0
+      IL_001a:  ldarg.1
+      IL_001b:  stfld      string valuetype TestModule/MyStructOption`1::_notNullField2
+      IL_0020:  ldloca.s   V_0
+      IL_0022:  ldarg.2
+      IL_0023:  stfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
+      IL_0028:  ldloca.s   V_0
+      IL_002a:  ldarg.3
+      IL_002b:  stfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
+      IL_0030:  ldloc.0
+      IL_0031:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsMyStructSome() cil managed
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
+                                                                                              string[]) = ( 01 00 01 04 00 00 00 0D 6E 6F 74 4E 75 6C 6C 46   
+                                                                                                            69 65 6C 64 32 0D 6E 6F 74 4E 75 6C 6C 46 69 65   
+                                                                                                            6C 64 31 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C   
+                                                                                                            64 32 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C 64   
+                                                                                                            31 00 00 )                                        
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
+      IL_0006:  ldc.i4.1
+      IL_0007:  ceq
+      IL_0009:  ret
+    } 
+
+    .method assembly specialname rtspecialname 
+            instance void  .ctor(int32 _tag) cil managed
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                              class [runtime]System.Type) = ( 01 00 60 06 00 00 1B 54 65 73 74 4D 6F 64 75 6C   
+                                                                                                                               65 2B 4D 79 53 74 72 75 63 74 4F 70 74 69 6F 6E   
+                                                                                                                               60 31 00 00 )                                     
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldarg.1
+      IL_0002:  stfld      int32 valuetype TestModule/MyStructOption`1::_tag
+      IL_0007:  ret
+    } 
+
+    .method public hidebysig instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> 
+            get_nestedGenericField() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance string 
+            get_notNullField2() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string valuetype TestModule/MyStructOption`1::_notNullField2
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance string 
+            get_canBeNullField() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance !T 
+            get_notNullField1() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance int32 
+            get_Tag() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      int32 valuetype TestModule/MyStructOption`1::_tag
+      IL_0006:  ret
+    } 
+
+    .method assembly hidebysig specialname 
+            instance object  __DebugDisplay() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+0.8A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  ldobj      valuetype TestModule/MyStructOption`1
+      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_001a:  ret
+    } 
+
+    .method public strict virtual instance string 
+            ToString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,valuetype TestModule/MyStructOption`1>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  ldobj      valuetype TestModule/MyStructOption`1
+      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_001a:  ret
+    } 
+
+    .property instance int32 Tag()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance int32 TestModule/MyStructOption`1::get_Tag()
+    } 
+    .property valuetype TestModule/MyStructOption`1
+            MyStructNone()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get valuetype TestModule/MyStructOption`1 TestModule/MyStructOption`1::get_MyStructNone()
+    } 
+    .property instance bool IsMyStructNone()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool TestModule/MyStructOption`1::get_IsMyStructNone()
+    } 
+    .property instance bool IsMyStructSome()
+    {
+      .custom instance void System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
+                                                                                              string[]) = ( 01 00 01 04 00 00 00 0D 6E 6F 74 4E 75 6C 6C 46   
+                                                                                                            69 65 6C 64 32 0D 6E 6F 74 4E 75 6C 6C 46 69 65   
+                                                                                                            6C 64 31 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C   
+                                                                                                            64 32 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C 64   
+                                                                                                            31 00 00 )                                        
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool TestModule/MyStructOption`1::get_IsMyStructSome()
+    } 
+    .property instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>
+            nestedGenericField()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> TestModule/MyStructOption`1::get_nestedGenericField()
+    } 
+    .property instance string notNullField2()
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance string TestModule/MyStructOption`1::get_notNullField2()
+    } 
+    .property instance string canBeNullField()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 02 00 00 00 00 00 ) 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance string TestModule/MyStructOption`1::get_canBeNullField()
+    } 
+    .property instance !T notNullField1()
+    {
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 03 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance !T TestModule/MyStructOption`1::get_notNullField1()
+    } 
+  } 
+
+  .method public static valuetype TestModule/MyStructOption`1 
+          mapStructContents(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f,
+                                 valuetype TestModule/MyStructOption`1 myOpt) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+    .param type a 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type b 
+      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param [0]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    .param [2]
+    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    
+    .maxstack  7
+    .locals init (valuetype TestModule/MyStructOption`1 V_0,
+             !!a V_1,
+             string V_2,
+             string V_3,
+             class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> V_4)
+    IL_0000:  ldarg.1
+    IL_0001:  stloc.0
+    IL_0002:  ldloca.s   V_0
+    IL_0004:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
+    IL_0009:  ldc.i4.1
+    IL_000a:  bne.un.s   IL_000e
+
+    IL_000c:  br.s       IL_0014
+
+    IL_000e:  call       valuetype TestModule/MyStructOption`1 valuetype TestModule/MyStructOption`1::get_MyStructNone()
+    IL_0013:  ret
+
+    IL_0014:  ldloca.s   V_0
+    IL_0016:  ldfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
+    IL_001b:  stloc.1
+    IL_001c:  ldloca.s   V_0
+    IL_001e:  ldfld      string valuetype TestModule/MyStructOption`1::_notNullField2
+    IL_0023:  stloc.2
+    IL_0024:  ldloca.s   V_0
+    IL_0026:  ldfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
+    IL_002b:  stloc.3
+    IL_002c:  ldloca.s   V_0
+    IL_002e:  ldfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
+    IL_0033:  stloc.s    V_4
+    IL_0035:  ldloc.s    V_4
+    IL_0037:  ldloc.2
+    IL_0038:  ldloc.3
+    IL_0039:  ldarg.0
+    IL_003a:  ldloc.1
+    IL_003b:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+    IL_0040:  call       valuetype TestModule/MyStructOption`1 valuetype TestModule/MyStructOption`1::NewMyStructSome(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>,
+                                                                                                                               string,
+                                                                                                                               string,
+                                                                                                                               !0)
+    IL_0045:  ret
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$TestModule
+       extends [runtime]System.Object
+{
+} 
+
+.class private auto ansi serializable sealed System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes
+       extends [runtime]System.Enum
+{
+  .custom instance void [runtime]System.FlagsAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public specialname rtspecialname int32 value__
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes All = int32(0xFFFFFFFF)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes None = int32(0x00000000)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicParameterlessConstructor = int32(0x00000001)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicConstructors = int32(0x00000003)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicConstructors = int32(0x00000004)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicMethods = int32(0x00000008)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicMethods = int32(0x00000010)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicFields = int32(0x00000020)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicFields = int32(0x00000040)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicNestedTypes = int32(0x00000080)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicNestedTypes = int32(0x00000100)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicProperties = int32(0x00000200)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicProperties = int32(0x00000400)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes PublicEvents = int32(0x00000800)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes NonPublicEvents = int32(0x00001000)
+  .field public static literal valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes Interfaces = int32(0x00002000)
+} 
+
+.class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute
+       extends [runtime]System.Attribute
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field private valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field private class [runtime]System.Type Type@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberType,
+                               class [runtime]System.Type Type) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::MemberType@
+    IL_000d:  ldarg.0
+    IL_000e:  ldarg.2
+    IL_000f:  stfld      class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::Type@
+    IL_0014:  ret
+  } 
+
+  .method public hidebysig specialname instance class [runtime]System.Type 
+          get_Type() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::Type@
+    IL_0006:  ret
+  } 
+
+  .method public hidebysig specialname instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes 
+          get_MemberType() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::MemberType@
+    IL_0006:  ret
+  } 
+
+  .property instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes
+          MemberType()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::get_MemberType()
+  } 
+  .property instance class [runtime]System.Type
+          Type()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance class [runtime]System.Type System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::get_Type()
+  } 
+} 
+
+.class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute
+       extends [runtime]System.Attribute
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field private bool ReturnValue@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field private string[] Members@
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(bool ReturnValue,
+                               string[] Members) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      bool System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::ReturnValue@
+    IL_000d:  ldarg.0
+    IL_000e:  ldarg.2
+    IL_000f:  stfld      string[] System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::Members@
+    IL_0014:  ret
+  } 
+
+  .method public hidebysig specialname instance string[] 
+          get_Members() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      string[] System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::Members@
+    IL_0006:  ret
+  } 
+
+  .method public hidebysig specialname instance bool 
+          get_ReturnValue() cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldfld      bool System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::ReturnValue@
+    IL_0006:  ret
+  } 
+
+  .property instance bool ReturnValue()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance bool System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::get_ReturnValue()
+  } 
+  .property instance string[] Members()
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .get instance string[] System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::get_Members()
+  } 
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+       extends [runtime]System.Attribute
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public uint8[] NullableFlags
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 scalarByteValue) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldc.i4.1
+    IL_0008:  newarr     [runtime]System.Byte
+    IL_000d:  dup
+    IL_000e:  ldc.i4.0
+    IL_000f:  ldarg.1
+    IL_0010:  stelem.i1
+    IL_0011:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_0016:  ret
+  } 
+
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8[] NullableFlags) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+    IL_000d:  ret
+  } 
+
+} 
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+       extends [runtime]System.Attribute
+{
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .field public uint8 Flag
+  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+  .method public specialname rtspecialname 
+          instance void  .ctor(uint8 Flag) cil managed
+  {
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
+    IL_0006:  ldarg.0
+    IL_0007:  ldarg.1
+    IL_0008:  stfld      uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+    IL_000d:  ret
+  } 
+
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericStructDu.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericStructDu.fs.il.netcore.bsl
new file mode 100644
index 00000000000..74b8ce8a49f
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericStructDu.fs.il.netcore.bsl
@@ -0,0 +1,415 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       
+.corflags 0x00000001    
+
+
+
+
+
+.class public abstract auto ansi sealed TestModule
+       extends [runtime]System.Object
+{
+  .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) 
+  .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+  .class sequential autochar serializable sealed nested public beforefieldinit MyStructOption`1
+         extends [runtime]System.ValueType
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
+                                                                                                         61 79 28 29 2C 6E 71 7D 00 00 )                   
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type T 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .class abstract auto ansi sealed nested public Tags
+           extends [runtime]System.Object
+    {
+      .param type T 
+        .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+      .field public static literal int32 MyStructNone = int32(0x00000000)
+      .field public static literal int32 MyStructSome = int32(0x00000001)
+    } 
+
+    .field assembly class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> _nestedGenericField
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly string _notNullField2
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly string _canBeNullField
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly !T _notNullField1
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .field assembly int32 _tag
+    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+    .method public static valuetype TestModule/MyStructOption`1 
+            get_MyStructNone() cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldc.i4.0
+      IL_0001:  newobj     instance void valuetype TestModule/MyStructOption`1::.ctor(int32)
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsMyStructNone() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
+      IL_0006:  ldc.i4.0
+      IL_0007:  ceq
+      IL_0009:  ret
+    } 
+
+    .method public static valuetype TestModule/MyStructOption`1 
+            NewMyStructSome(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> _nestedGenericField,
+                            string _notNullField2,
+                            string _canBeNullField,
+                            !T _notNullField1) cil managed
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
+      .param [1]
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
+      .param [3]
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  5
+      .locals init (valuetype TestModule/MyStructOption`1 V_0)
+      IL_0000:  ldloca.s   V_0
+      IL_0002:  initobj    valuetype TestModule/MyStructOption`1
+      IL_0008:  ldloca.s   V_0
+      IL_000a:  ldc.i4.1
+      IL_000b:  stfld      int32 valuetype TestModule/MyStructOption`1::_tag
+      IL_0010:  ldloca.s   V_0
+      IL_0012:  ldarg.0
+      IL_0013:  stfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
+      IL_0018:  ldloca.s   V_0
+      IL_001a:  ldarg.1
+      IL_001b:  stfld      string valuetype TestModule/MyStructOption`1::_notNullField2
+      IL_0020:  ldloca.s   V_0
+      IL_0022:  ldarg.2
+      IL_0023:  stfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
+      IL_0028:  ldloca.s   V_0
+      IL_002a:  ldarg.3
+      IL_002b:  stfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
+      IL_0030:  ldloc.0
+      IL_0031:  ret
+    } 
+
+    .method public hidebysig instance bool 
+            get_IsMyStructSome() cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
+                                                                                                              string[]) = ( 01 00 01 04 00 00 00 0D 6E 6F 74 4E 75 6C 6C 46   
+                                                                                                                            69 65 6C 64 32 0D 6E 6F 74 4E 75 6C 6C 46 69 65   
+                                                                                                                            6C 64 31 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C   
+                                                                                                                            64 32 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C 64   
+                                                                                                                            31 00 00 )                                        
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
+      IL_0006:  ldc.i4.1
+      IL_0007:  ceq
+      IL_0009:  ret
+    } 
+
+    .method assembly specialname rtspecialname 
+            instance void  .ctor(int32 _tag) cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
+                                                                                                              class [runtime]System.Type) = ( 01 00 60 06 00 00 1B 54 65 73 74 4D 6F 64 75 6C   
+                                                                                                                                                     65 2B 4D 79 53 74 72 75 63 74 4F 70 74 69 6F 6E   
+                                                                                                                                                     60 31 00 00 )                                     
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldarg.1
+      IL_0002:  stfld      int32 valuetype TestModule/MyStructOption`1::_tag
+      IL_0007:  ret
+    } 
+
+    .method public hidebysig instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> 
+            get_nestedGenericField() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance string 
+            get_notNullField2() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string valuetype TestModule/MyStructOption`1::_notNullField2
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance string 
+            get_canBeNullField() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance !T 
+            get_notNullField1() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .param [0]
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
+      IL_0006:  ret
+    } 
+
+    .method public hidebysig instance int32 
+            get_Tag() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldfld      int32 valuetype TestModule/MyStructOption`1::_tag
+      IL_0006:  ret
+    } 
+
+    .method assembly hidebysig specialname 
+            instance object  __DebugDisplay() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+0.8A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  ldobj      valuetype TestModule/MyStructOption`1
+      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_001a:  ret
+    } 
+
+    .method public strict virtual instance string 
+            ToString() cil managed
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldstr      "%+A"
+      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,valuetype TestModule/MyStructOption`1>::.ctor(string)
+      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
+      IL_000f:  ldarg.0
+      IL_0010:  ldobj      valuetype TestModule/MyStructOption`1
+      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
+      IL_001a:  ret
+    } 
+
+    .property instance int32 Tag()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance int32 TestModule/MyStructOption`1::get_Tag()
+    } 
+    .property valuetype TestModule/MyStructOption`1
+            MyStructNone()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get valuetype TestModule/MyStructOption`1 TestModule/MyStructOption`1::get_MyStructNone()
+    } 
+    .property instance bool IsMyStructNone()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool TestModule/MyStructOption`1::get_IsMyStructNone()
+    } 
+    .property instance bool IsMyStructSome()
+    {
+      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
+                                                                                                              string[]) = ( 01 00 01 04 00 00 00 0D 6E 6F 74 4E 75 6C 6C 46   
+                                                                                                                            69 65 6C 64 32 0D 6E 6F 74 4E 75 6C 6C 46 69 65   
+                                                                                                                            6C 64 31 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C   
+                                                                                                                            64 32 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C 64   
+                                                                                                                            31 00 00 )                                        
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
+      .get instance bool TestModule/MyStructOption`1::get_IsMyStructSome()
+    } 
+    .property instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>
+            nestedGenericField()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> TestModule/MyStructOption`1::get_nestedGenericField()
+    } 
+    .property instance string notNullField2()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance string TestModule/MyStructOption`1::get_notNullField2()
+    } 
+    .property instance string canBeNullField()
+    {
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 02 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance string TestModule/MyStructOption`1::get_canBeNullField()
+    } 
+    .property instance !T notNullField1()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
+                                                                                                  int32,
+                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 03 00 00 00 00 00 ) 
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .get instance !T TestModule/MyStructOption`1::get_notNullField1()
+    } 
+  } 
+
+  .method public static valuetype TestModule/MyStructOption`1 
+          mapStructContents(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f,
+                                 valuetype TestModule/MyStructOption`1 myOpt) cil managed
+  {
+    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
+    .param type a 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param type b 
+      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
+    .param [0]
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    .param [2]
+    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
+    
+    .maxstack  7
+    .locals init (valuetype TestModule/MyStructOption`1 V_0,
+             !!a V_1,
+             string V_2,
+             string V_3,
+             class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> V_4)
+    IL_0000:  ldarg.1
+    IL_0001:  stloc.0
+    IL_0002:  ldloca.s   V_0
+    IL_0004:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
+    IL_0009:  ldc.i4.1
+    IL_000a:  bne.un.s   IL_000e
+
+    IL_000c:  br.s       IL_0014
+
+    IL_000e:  call       valuetype TestModule/MyStructOption`1 valuetype TestModule/MyStructOption`1::get_MyStructNone()
+    IL_0013:  ret
+
+    IL_0014:  ldloca.s   V_0
+    IL_0016:  ldfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
+    IL_001b:  stloc.1
+    IL_001c:  ldloca.s   V_0
+    IL_001e:  ldfld      string valuetype TestModule/MyStructOption`1::_notNullField2
+    IL_0023:  stloc.2
+    IL_0024:  ldloca.s   V_0
+    IL_0026:  ldfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
+    IL_002b:  stloc.3
+    IL_002c:  ldloca.s   V_0
+    IL_002e:  ldfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
+    IL_0033:  stloc.s    V_4
+    IL_0035:  ldloc.s    V_4
+    IL_0037:  ldloc.2
+    IL_0038:  ldloc.3
+    IL_0039:  ldarg.0
+    IL_003a:  ldloc.1
+    IL_003b:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
+    IL_0040:  call       valuetype TestModule/MyStructOption`1 valuetype TestModule/MyStructOption`1::NewMyStructSome(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>,
+                                                                                                                               string,
+                                                                                                                               string,
+                                                                                                                               !0)
+    IL_0045:  ret
+  } 
+
+} 
+
+.class private abstract auto ansi sealed ''.$TestModule
+       extends [runtime]System.Object
+{
+} 
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs
index f6038521066..043675e4bcc 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs
@@ -20,14 +20,4 @@ type MyOptionWhichCannotHaveNullInTheInside<'T when 'T:not null> =
 let mapNotNullableContents f myOpt =
     match myOpt with
     | MyNotNullNone -> MyNotNullNone
-    | MyNotNullSome x -> MyNotNullSome (f x)
-
-[]
-type MyStructOption<'T when 'T: not null> = 
-    | MyStructNone
-    | MyStructSome of nestedGenericField : list> * notNullField2 : string * canBeNullField : (string | null) * notNullField1 : 'T
-
-let mapStructContents f myOpt =
-    match myOpt with
-    | MyStructNone -> MyStructNone
-    | MyStructSome(ngf,s,ns,x) -> MyStructSome (ngf,s,ns,f x)
\ No newline at end of file
+    | MyNotNullSome x -> MyNotNullSome (f x)
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl
index f2a1074fb26..66fa1c78b4d 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl
@@ -170,6 +170,30 @@
       IL_0015:  ret
     } 
 
+    .method public specialname static bool 
+            get_IsMyNone(class TestModule/MyNullableOption`1 A_0) cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldnull
+      IL_0002:  ceq
+      IL_0004:  ret
+    } 
+
+    .method public specialname static bool 
+            get_IsMySome(class TestModule/MyNullableOption`1 A_0) cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldnull
+      IL_0002:  cgt.un
+      IL_0004:  ret
+    } 
+
     .property class TestModule/MyNullableOption`1
             MyNone()
     {
@@ -188,6 +212,20 @@
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .get instance !T TestModule/MyNullableOption`1::get_value()
     } 
+    .property bool IsMyNone()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .get bool TestModule/MyNullableOption`1::get_IsMyNone(class TestModule/MyNullableOption`1)
+    } 
+    .property bool IsMySome()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .get bool TestModule/MyNullableOption`1::get_IsMySome(class TestModule/MyNullableOption`1)
+    } 
   } 
 
   .class auto autochar serializable sealed nested public beforefieldinit MyOptionWhichCannotHaveNullInTheInside`1
@@ -335,340 +373,61 @@
       IL_0015:  ret
     } 
 
-    .property class TestModule/MyOptionWhichCannotHaveNullInTheInside`1
-            MyNotNullNone()
+    .method public specialname static bool 
+            get_IsMyNotNullNone(class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 A_0) cil managed
     {
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-      .get class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_MyNotNullNone()
-    } 
-    .property instance !T 'value'()
-    {
-      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
-                                                                                                  int32,
-                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .get instance !T TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_value()
-    } 
-  } 
-
-  .class sequential autochar serializable sealed nested public beforefieldinit MyStructOption`1
-         extends [runtime]System.ValueType
-  {
-    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
-                                                                                                   61 79 28 29 2C 6E 71 7D 00 00 )                   
-    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
-    .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
-    .param type T 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
-    .class abstract auto ansi sealed nested public Tags
-           extends [runtime]System.Object
-    {
-      .param type T 
-        .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
-      .field public static literal int32 MyStructNone = int32(0x00000000)
-      .field public static literal int32 MyStructSome = int32(0x00000001)
-    } 
-
-    .field assembly class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> _nestedGenericField
-    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    .field assembly string _notNullField2
-    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    .field assembly string _canBeNullField
-    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    .field assembly !T _notNullField1
-    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    .field assembly int32 _tag
-    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    .method public static valuetype TestModule/MyStructOption`1 
-            get_MyStructNone() cil managed
-    {
-      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
-                                                                                                  int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldc.i4.0
-      IL_0001:  newobj     instance void valuetype TestModule/MyStructOption`1::.ctor(int32)
-      IL_0006:  ret
-    } 
-
-    .method public hidebysig instance bool 
-            get_IsMyStructNone() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
-      IL_0006:  ldc.i4.0
-      IL_0007:  ceq
-      IL_0009:  ret
-    } 
-
-    .method public static valuetype TestModule/MyStructOption`1 
-            NewMyStructSome(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> _nestedGenericField,
-                            string _notNullField2,
-                            string _canBeNullField,
-                            !T _notNullField1) cil managed
-    {
-      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
-                                                                                                  int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
-      .param [1]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
-      .param [3]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
-      
-      .maxstack  5
-      .locals init (valuetype TestModule/MyStructOption`1 V_0)
-      IL_0000:  ldloca.s   V_0
-      IL_0002:  initobj    valuetype TestModule/MyStructOption`1
-      IL_0008:  ldloca.s   V_0
-      IL_000a:  ldc.i4.1
-      IL_000b:  stfld      int32 valuetype TestModule/MyStructOption`1::_tag
-      IL_0010:  ldloca.s   V_0
-      IL_0012:  ldarg.0
-      IL_0013:  stfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
-      IL_0018:  ldloca.s   V_0
-      IL_001a:  ldarg.1
-      IL_001b:  stfld      string valuetype TestModule/MyStructOption`1::_notNullField2
-      IL_0020:  ldloca.s   V_0
-      IL_0022:  ldarg.2
-      IL_0023:  stfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
-      IL_0028:  ldloca.s   V_0
-      IL_002a:  ldarg.3
-      IL_002b:  stfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
-      IL_0030:  ldloc.0
-      IL_0031:  ret
-    } 
-
-    .method public hidebysig instance bool 
-            get_IsMyStructSome() cil managed
-    {
-      .custom instance void System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
-                                                                                              string[]) = ( 01 00 01 04 00 00 00 0D 6E 6F 74 4E 75 6C 6C 46   
-                                                                                                            69 65 6C 64 32 0D 6E 6F 74 4E 75 6C 6C 46 69 65   
-                                                                                                            6C 64 31 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C   
-                                                                                                            64 32 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C 64   
-                                                                                                            31 00 00 )                                        
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldarg.0
-      IL_0001:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
-      IL_0006:  ldc.i4.1
-      IL_0007:  ceq
-      IL_0009:  ret
+      IL_0001:  ldnull
+      IL_0002:  ceq
+      IL_0004:  ret
     } 
 
-    .method assembly specialname rtspecialname 
-            instance void  .ctor(int32 _tag) cil managed
+    .method public specialname static bool 
+            get_IsMyNotNullSome(class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 A_0) cil managed
     {
-      .custom instance void System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
-                                                                                              class [runtime]System.Type) = ( 01 00 60 06 00 00 1B 54 65 73 74 4D 6F 64 75 6C   
-                                                                                                                               65 2B 4D 79 53 74 72 75 63 74 4F 70 74 69 6F 6E   
-                                                                                                                               60 31 00 00 )                                     
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldarg.0
-      IL_0001:  ldarg.1
-      IL_0002:  stfld      int32 valuetype TestModule/MyStructOption`1::_tag
-      IL_0007:  ret
+      IL_0001:  ldnull
+      IL_0002:  cgt.un
+      IL_0004:  ret
     } 
 
-    .method public hidebysig instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> 
-            get_nestedGenericField() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  ldfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
-      IL_0006:  ret
-    } 
-
-    .method public hidebysig instance string 
-            get_notNullField2() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  ldfld      string valuetype TestModule/MyStructOption`1::_notNullField2
-      IL_0006:  ret
-    } 
-
-    .method public hidebysig instance string 
-            get_canBeNullField() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .param [0]
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  ldfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
-      IL_0006:  ret
-    } 
-
-    .method public hidebysig instance !T 
-            get_notNullField1() cil managed
+    .property class TestModule/MyOptionWhichCannotHaveNullInTheInside`1
+            MyNotNullNone()
     {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .param [0]
       .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  ldfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
-      IL_0006:  ret
-    } 
-
-    .method public hidebysig instance int32 
-            get_Tag() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  ldfld      int32 valuetype TestModule/MyStructOption`1::_tag
-      IL_0006:  ret
-    } 
-
-    .method assembly hidebysig specialname 
-            instance object  __DebugDisplay() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldstr      "%+0.8A"
-      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string)
-      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
-      IL_000f:  ldarg.0
-      IL_0010:  ldobj      valuetype TestModule/MyStructOption`1
-      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
-      IL_001a:  ret
-    } 
-
-    .method public strict virtual instance string 
-            ToString() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldstr      "%+A"
-      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,valuetype TestModule/MyStructOption`1>::.ctor(string)
-      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
-      IL_000f:  ldarg.0
-      IL_0010:  ldobj      valuetype TestModule/MyStructOption`1
-      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
-      IL_001a:  ret
-    } 
-
-    .property instance int32 Tag()
-    {
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-      .get instance int32 TestModule/MyStructOption`1::get_Tag()
-    } 
-    .property valuetype TestModule/MyStructOption`1
-            MyStructNone()
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-      .get valuetype TestModule/MyStructOption`1 TestModule/MyStructOption`1::get_MyStructNone()
-    } 
-    .property instance bool IsMyStructNone()
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-      .get instance bool TestModule/MyStructOption`1::get_IsMyStructNone()
-    } 
-    .property instance bool IsMyStructSome()
-    {
-      .custom instance void System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
-                                                                                              string[]) = ( 01 00 01 04 00 00 00 0D 6E 6F 74 4E 75 6C 6C 46   
-                                                                                                            69 65 6C 64 32 0D 6E 6F 74 4E 75 6C 6C 46 69 65   
-                                                                                                            6C 64 31 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C   
-                                                                                                            64 32 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C 64   
-                                                                                                            31 00 00 )                                        
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-      .get instance bool TestModule/MyStructOption`1::get_IsMyStructSome()
+      .get class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_MyNotNullNone()
     } 
-    .property instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>
-            nestedGenericField()
+    .property instance !T 'value'()
     {
       .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                   int32,
                                                                                                   int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .get instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> TestModule/MyStructOption`1::get_nestedGenericField()
-    } 
-    .property instance string notNullField2()
-    {
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
-      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
-                                                                                                  int32,
-                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .get instance string TestModule/MyStructOption`1::get_notNullField2()
+      .get instance !T TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_value()
     } 
-    .property instance string canBeNullField()
+    .property bool IsMyNotNullNone()
     {
-      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
-                                                                                                  int32,
-                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 02 00 00 00 00 00 ) 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .get instance string TestModule/MyStructOption`1::get_canBeNullField()
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .get bool TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_IsMyNotNullNone(class TestModule/MyOptionWhichCannotHaveNullInTheInside`1)
     } 
-    .property instance !T notNullField1()
+    .property bool IsMyNotNullSome()
     {
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
-      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
-                                                                                                  int32,
-                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 03 00 00 00 00 00 ) 
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .get instance !T TestModule/MyStructOption`1::get_notNullField1()
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .get bool TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_IsMyNotNullSome(class TestModule/MyOptionWhichCannotHaveNullInTheInside`1)
     } 
   } 
 
@@ -744,63 +503,6 @@
     IL_001e:  ret
   } 
 
-  .method public static valuetype TestModule/MyStructOption`1 
-          mapStructContents(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f,
-                                 valuetype TestModule/MyStructOption`1 myOpt) cil managed
-  {
-    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
-    .param type a 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
-    .param type b 
-      .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
-    .param [0]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
-    .param [2]
-    .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
-    
-    .maxstack  7
-    .locals init (valuetype TestModule/MyStructOption`1 V_0,
-             !!a V_1,
-             string V_2,
-             string V_3,
-             class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> V_4)
-    IL_0000:  ldarg.1
-    IL_0001:  stloc.0
-    IL_0002:  ldloca.s   V_0
-    IL_0004:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
-    IL_0009:  ldc.i4.1
-    IL_000a:  bne.un.s   IL_000e
-
-    IL_000c:  br.s       IL_0014
-
-    IL_000e:  call       valuetype TestModule/MyStructOption`1 valuetype TestModule/MyStructOption`1::get_MyStructNone()
-    IL_0013:  ret
-
-    IL_0014:  ldloca.s   V_0
-    IL_0016:  ldfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
-    IL_001b:  stloc.1
-    IL_001c:  ldloca.s   V_0
-    IL_001e:  ldfld      string valuetype TestModule/MyStructOption`1::_notNullField2
-    IL_0023:  stloc.2
-    IL_0024:  ldloca.s   V_0
-    IL_0026:  ldfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
-    IL_002b:  stloc.3
-    IL_002c:  ldloca.s   V_0
-    IL_002e:  ldfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
-    IL_0033:  stloc.s    V_4
-    IL_0035:  ldloc.s    V_4
-    IL_0037:  ldloc.2
-    IL_0038:  ldloc.3
-    IL_0039:  ldarg.0
-    IL_003a:  ldloc.1
-    IL_003b:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
-    IL_0040:  call       valuetype TestModule/MyStructOption`1 valuetype TestModule/MyStructOption`1::NewMyStructSome(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>,
-                                                                                                                               string,
-                                                                                                                               string,
-                                                                                                                               !0)
-    IL_0045:  ret
-  } 
-
 } 
 
 .class private abstract auto ansi sealed ''.$TestModule
@@ -902,73 +604,6 @@
   } 
 } 
 
-.class private auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute
-       extends [runtime]System.Attribute
-{
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .field private bool ReturnValue@
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .field private string[] Members@
-  .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-  .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-  .method public specialname rtspecialname 
-          instance void  .ctor(bool ReturnValue,
-                               string[] Members) cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  call       instance void [runtime]System.Attribute::.ctor()
-    IL_0006:  ldarg.0
-    IL_0007:  ldarg.1
-    IL_0008:  stfld      bool System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::ReturnValue@
-    IL_000d:  ldarg.0
-    IL_000e:  ldarg.2
-    IL_000f:  stfld      string[] System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::Members@
-    IL_0014:  ret
-  } 
-
-  .method public hidebysig specialname instance string[] 
-          get_Members() cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  ldfld      string[] System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::Members@
-    IL_0006:  ret
-  } 
-
-  .method public hidebysig specialname instance bool 
-          get_ReturnValue() cil managed
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    
-    .maxstack  8
-    IL_0000:  ldarg.0
-    IL_0001:  ldfld      bool System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::ReturnValue@
-    IL_0006:  ret
-  } 
-
-  .property instance bool ReturnValue()
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    .get instance bool System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::get_ReturnValue()
-  } 
-  .property instance string[] Members()
-  {
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    .get instance string[] System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::get_Members()
-  } 
-} 
-
 .class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
        extends [runtime]System.Attribute
 {
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl
index e7c127ead88..31eb914a6f2 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl
@@ -170,6 +170,30 @@
       IL_0015:  ret
     } 
 
+    .method public specialname static bool 
+            get_IsMyNone(class TestModule/MyNullableOption`1 A_0) cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldnull
+      IL_0002:  ceq
+      IL_0004:  ret
+    } 
+
+    .method public specialname static bool 
+            get_IsMySome(class TestModule/MyNullableOption`1 A_0) cil managed
+    {
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      
+      .maxstack  8
+      IL_0000:  ldarg.0
+      IL_0001:  ldnull
+      IL_0002:  cgt.un
+      IL_0004:  ret
+    } 
+
     .property class TestModule/MyNullableOption`1
             MyNone()
     {
@@ -188,6 +212,20 @@
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .get instance !T TestModule/MyNullableOption`1::get_value()
     } 
+    .property bool IsMyNone()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .get bool TestModule/MyNullableOption`1::get_IsMyNone(class TestModule/MyNullableOption`1)
+    } 
+    .property bool IsMySome()
+    {
+      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .get bool TestModule/MyNullableOption`1::get_IsMySome(class TestModule/MyNullableOption`1)
+    } 
   } 
 
   .class auto autochar serializable sealed nested public beforefieldinit MyOptionWhichCannotHaveNullInTheInside`1
@@ -335,340 +373,61 @@
       IL_0015:  ret
     } 
 
-    .property class TestModule/MyOptionWhichCannotHaveNullInTheInside`1
-            MyNotNullNone()
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-      .get class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_MyNotNullNone()
-    } 
-    .property instance !T 'value'()
-    {
-      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
-                                                                                                  int32,
-                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .get instance !T TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_value()
-    } 
-  } 
-
-  .class sequential autochar serializable sealed nested public beforefieldinit MyStructOption`1
-         extends [runtime]System.ValueType
-  {
-    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C   
-                                                                                                         61 79 28 29 2C 6E 71 7D 00 00 )                   
-    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) 
-    .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
-    .param type T 
-      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
-    .class abstract auto ansi sealed nested public Tags
-           extends [runtime]System.Object
-    {
-      .param type T 
-        .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
-      .field public static literal int32 MyStructNone = int32(0x00000000)
-      .field public static literal int32 MyStructSome = int32(0x00000001)
-    } 
-
-    .field assembly class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> _nestedGenericField
-    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    .field assembly string _notNullField2
-    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    .field assembly string _canBeNullField
-    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    .field assembly !T _notNullField1
-    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    .field assembly int32 _tag
-    .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-    .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-    .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-    .method public static valuetype TestModule/MyStructOption`1 
-            get_MyStructNone() cil managed
-    {
-      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
-                                                                                                  int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldc.i4.0
-      IL_0001:  newobj     instance void valuetype TestModule/MyStructOption`1::.ctor(int32)
-      IL_0006:  ret
-    } 
-
-    .method public hidebysig instance bool 
-            get_IsMyStructNone() cil managed
+    .method public specialname static bool 
+            get_IsMyNotNullNone(class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 A_0) cil managed
     {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldarg.0
-      IL_0001:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
-      IL_0006:  ldc.i4.0
-      IL_0007:  ceq
-      IL_0009:  ret
+      IL_0001:  ldnull
+      IL_0002:  ceq
+      IL_0004:  ret
     } 
 
-    .method public static valuetype TestModule/MyStructOption`1 
-            NewMyStructSome(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> _nestedGenericField,
-                            string _notNullField2,
-                            string _canBeNullField,
-                            !T _notNullField1) cil managed
+    .method public specialname static bool 
+            get_IsMyNotNullSome(class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 A_0) cil managed
     {
-      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
-                                                                                                  int32) = ( 01 00 08 00 00 00 01 00 00 00 00 00 ) 
-      .param [1]
-      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 02 00 00 ) 
-      .param [3]
-      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
-      
-      .maxstack  5
-      .locals init (valuetype TestModule/MyStructOption`1 V_0)
-      IL_0000:  ldloca.s   V_0
-      IL_0002:  initobj    valuetype TestModule/MyStructOption`1
-      IL_0008:  ldloca.s   V_0
-      IL_000a:  ldc.i4.1
-      IL_000b:  stfld      int32 valuetype TestModule/MyStructOption`1::_tag
-      IL_0010:  ldloca.s   V_0
-      IL_0012:  ldarg.0
-      IL_0013:  stfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
-      IL_0018:  ldloca.s   V_0
-      IL_001a:  ldarg.1
-      IL_001b:  stfld      string valuetype TestModule/MyStructOption`1::_notNullField2
-      IL_0020:  ldloca.s   V_0
-      IL_0022:  ldarg.2
-      IL_0023:  stfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
-      IL_0028:  ldloca.s   V_0
-      IL_002a:  ldarg.3
-      IL_002b:  stfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
-      IL_0030:  ldloc.0
-      IL_0031:  ret
-    } 
-
-    .method public hidebysig instance bool 
-            get_IsMyStructSome() cil managed
-    {
-      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
-                                                                                                              string[]) = ( 01 00 01 04 00 00 00 0D 6E 6F 74 4E 75 6C 6C 46   
-                                                                                                                            69 65 6C 64 32 0D 6E 6F 74 4E 75 6C 6C 46 69 65   
-                                                                                                                            6C 64 31 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C   
-                                                                                                                            64 32 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C 64   
-                                                                                                                            31 00 00 )                                        
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       
       .maxstack  8
       IL_0000:  ldarg.0
-      IL_0001:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
-      IL_0006:  ldc.i4.1
-      IL_0007:  ceq
-      IL_0009:  ret
+      IL_0001:  ldnull
+      IL_0002:  cgt.un
+      IL_0004:  ret
     } 
 
-    .method assembly specialname rtspecialname 
-            instance void  .ctor(int32 _tag) cil managed
-    {
-      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,
-                                                                                                              class [runtime]System.Type) = ( 01 00 60 06 00 00 1B 54 65 73 74 4D 6F 64 75 6C   
-                                                                                                                                                     65 2B 4D 79 53 74 72 75 63 74 4F 70 74 69 6F 6E   
-                                                                                                                                                     60 31 00 00 )                                     
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  ldarg.1
-      IL_0002:  stfld      int32 valuetype TestModule/MyStructOption`1::_tag
-      IL_0007:  ret
-    } 
-
-    .method public hidebysig instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> 
-            get_nestedGenericField() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .param [0]
-      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  ldfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
-      IL_0006:  ret
-    } 
-
-    .method public hidebysig instance string 
-            get_notNullField2() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .param [0]
-      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  ldfld      string valuetype TestModule/MyStructOption`1::_notNullField2
-      IL_0006:  ret
-    } 
-
-    .method public hidebysig instance string 
-            get_canBeNullField() cil managed
+    .property class TestModule/MyOptionWhichCannotHaveNullInTheInside`1
+            MyNotNullNone()
     {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .param [0]
       .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  ldfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
-      IL_0006:  ret
-    } 
-
-    .method public hidebysig instance !T 
-            get_notNullField1() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .param [0]
-      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  ldfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
-      IL_0006:  ret
-    } 
-
-    .method public hidebysig instance int32 
-            get_Tag() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldarg.0
-      IL_0001:  ldfld      int32 valuetype TestModule/MyStructOption`1::_tag
-      IL_0006:  ret
-    } 
-
-    .method assembly hidebysig specialname 
-            instance object  __DebugDisplay() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldstr      "%+0.8A"
-      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string)
-      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
-      IL_000f:  ldarg.0
-      IL_0010:  ldobj      valuetype TestModule/MyStructOption`1
-      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
-      IL_001a:  ret
-    } 
-
-    .method public strict virtual instance string 
-            ToString() cil managed
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      
-      .maxstack  8
-      IL_0000:  ldstr      "%+A"
-      IL_0005:  newobj     instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,valuetype TestModule/MyStructOption`1>::.ctor(string)
-      IL_000a:  call       !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4)
-      IL_000f:  ldarg.0
-      IL_0010:  ldobj      valuetype TestModule/MyStructOption`1
-      IL_0015:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0)
-      IL_001a:  ret
-    } 
-
-    .property instance int32 Tag()
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-      .get instance int32 TestModule/MyStructOption`1::get_Tag()
-    } 
-    .property valuetype TestModule/MyStructOption`1
-            MyStructNone()
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-      .get valuetype TestModule/MyStructOption`1 TestModule/MyStructOption`1::get_MyStructNone()
-    } 
-    .property instance bool IsMyStructNone()
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-      .get instance bool TestModule/MyStructOption`1::get_IsMyStructNone()
-    } 
-    .property instance bool IsMyStructSome()
-    {
-      .custom instance void [runtime]System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute::.ctor(bool,
-                                                                                                              string[]) = ( 01 00 01 04 00 00 00 0D 6E 6F 74 4E 75 6C 6C 46   
-                                                                                                                            69 65 6C 64 32 0D 6E 6F 74 4E 75 6C 6C 46 69 65   
-                                                                                                                            6C 64 31 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C   
-                                                                                                                            64 32 0E 5F 6E 6F 74 4E 75 6C 6C 46 69 65 6C 64   
-                                                                                                                            31 00 00 )                                        
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) 
-      .get instance bool TestModule/MyStructOption`1::get_IsMyStructSome()
+      .get class TestModule/MyOptionWhichCannotHaveNullInTheInside`1 TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_MyNotNullNone()
     } 
-    .property instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>
-            nestedGenericField()
+    .property instance !T 'value'()
     {
       .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
                                                                                                   int32,
                                                                                                   int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
-      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 01 02 00 00 ) 
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .get instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> TestModule/MyStructOption`1::get_nestedGenericField()
+      .get instance !T TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_value()
     } 
-    .property instance string notNullField2()
+    .property bool IsMyNotNullNone()
     {
-      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
-      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
-                                                                                                  int32,
-                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .get instance string TestModule/MyStructOption`1::get_notNullField2()
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .get bool TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_IsMyNotNullNone(class TestModule/MyOptionWhichCannotHaveNullInTheInside`1)
     } 
-    .property instance string canBeNullField()
+    .property bool IsMyNotNullSome()
     {
-      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
-                                                                                                  int32,
-                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 02 00 00 00 00 00 ) 
-      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
       .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
       .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .get instance string TestModule/MyStructOption`1::get_canBeNullField()
-    } 
-    .property instance !T notNullField1()
-    {
-      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) 
-      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
-                                                                                                  int32,
-                                                                                                  int32) = ( 01 00 04 00 00 00 01 00 00 00 03 00 00 00 00 00 ) 
-      .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
-      .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) 
-      .get instance !T TestModule/MyStructOption`1::get_notNullField1()
+      .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 00 00 00 00 00 00 ) 
+      .get bool TestModule/MyOptionWhichCannotHaveNullInTheInside`1::get_IsMyNotNullSome(class TestModule/MyOptionWhichCannotHaveNullInTheInside`1)
     } 
   } 
 
@@ -744,63 +503,6 @@
     IL_001e:  ret
   } 
 
-  .method public static valuetype TestModule/MyStructOption`1 
-          mapStructContents(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f,
-                                 valuetype TestModule/MyStructOption`1 myOpt) cil managed
-  {
-    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) 
-    .param type a 
-      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
-    .param type b 
-      .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) 
-    .param [0]
-    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
-    .param [2]
-    .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) 
-    
-    .maxstack  7
-    .locals init (valuetype TestModule/MyStructOption`1 V_0,
-             !!a V_1,
-             string V_2,
-             string V_3,
-             class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> V_4)
-    IL_0000:  ldarg.1
-    IL_0001:  stloc.0
-    IL_0002:  ldloca.s   V_0
-    IL_0004:  call       instance int32 valuetype TestModule/MyStructOption`1::get_Tag()
-    IL_0009:  ldc.i4.1
-    IL_000a:  bne.un.s   IL_000e
-
-    IL_000c:  br.s       IL_0014
-
-    IL_000e:  call       valuetype TestModule/MyStructOption`1 valuetype TestModule/MyStructOption`1::get_MyStructNone()
-    IL_0013:  ret
-
-    IL_0014:  ldloca.s   V_0
-    IL_0016:  ldfld      !0 valuetype TestModule/MyStructOption`1::_notNullField1
-    IL_001b:  stloc.1
-    IL_001c:  ldloca.s   V_0
-    IL_001e:  ldfld      string valuetype TestModule/MyStructOption`1::_notNullField2
-    IL_0023:  stloc.2
-    IL_0024:  ldloca.s   V_0
-    IL_0026:  ldfld      string valuetype TestModule/MyStructOption`1::_canBeNullField
-    IL_002b:  stloc.3
-    IL_002c:  ldloca.s   V_0
-    IL_002e:  ldfld      class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> valuetype TestModule/MyStructOption`1::_nestedGenericField
-    IL_0033:  stloc.s    V_4
-    IL_0035:  ldloc.s    V_4
-    IL_0037:  ldloc.2
-    IL_0038:  ldloc.3
-    IL_0039:  ldarg.0
-    IL_003a:  ldloc.1
-    IL_003b:  callvirt   instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
-    IL_0040:  call       valuetype TestModule/MyStructOption`1 valuetype TestModule/MyStructOption`1::NewMyStructSome(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>,
-                                                                                                                               string,
-                                                                                                                               string,
-                                                                                                                               !0)
-    IL_0045:  ret
-  } 
-
 } 
 
 .class private abstract auto ansi sealed ''.$TestModule
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs
index fc9425ee4e2..0c9774032e8 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs
@@ -69,6 +69,11 @@ let ``Nullable attr for Option clones`` compilation =
     compilation
     |> verifyCompilation DoNotOptimize
 
+[]
+let ``Generic struct DU`` compilation =  
+    compilation
+    |> verifyCompilation DoNotOptimize
+
 
 module Interop  =
     open System.IO
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index 58cda3a52bd..56e23439441 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -221,6 +221,7 @@
 	
 	
 	
+    
     
     
     
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/DiscriminatedUnionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/DiscriminatedUnionTests.fs
index abd5fb6e3b6..194284177cc 100644
--- a/tests/FSharp.Compiler.ComponentTests/Language/DiscriminatedUnionTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Language/DiscriminatedUnionTests.fs
@@ -49,6 +49,41 @@ if foo.IsA then failwith "Should not be A"
         |> compileExeAndRun
         |> shouldSucceed
 
+    // TODO nullness - wait for https://github.com/fsharp/fslang-design/discussions/760
+    // []
+    let ``Is* DU property roundtrip over pickled metadata and with fsi file`` () = 
+        let libCode =  """module rec TestLib
+
+type X = A | B"""
+        let appCode = """
+let x = TestLib.X.A
+let isA = x.IsA
+printfn "%A" isA """
+        let lib = 
+            Fsi(libCode)
+            |> withAdditionalSourceFile (FsSource libCode)
+            |> withLangVersionPreview
+            |> asLibrary
+            |> withName "fsLib"
+
+        lib
+        |> compile
+        |> verifyIL [""".method public hidebysig specialname 
+instance bool  get_IsA() cil managed """]
+
+        FSharp appCode
+        |> asExe
+        |> withReferences [lib]
+        |> withWarnOn 3186
+        |> withOptions ["--warnaserror+"]
+        |> withName "AppCodeProjectName"
+        |> withLangVersionPreview
+        |> compile
+        |> shouldFail
+        |> withDiagnosticMessageMatches "does not define the field, constructor or member 'IsA'"
+
+    
+
     []
     let ``Is* discriminated union properties with backticks are visible, proper values are returned`` () =
         Fsx """
@@ -130,7 +165,8 @@ let isFoo = foo.IsFoo
         |> withErrorMessage "The type 'Foo' does not define the field, constructor or member 'IsFoo'. Maybe you want one of the following:
    Foo"
 
-    []
+    // TODO nullness - wait for https://github.com/fsharp/fslang-design/discussions/760
+    //[]
     let ``Is* discriminated union properties are unavailable on voption`` () =
         Fsx """
 let x = (ValueSome 1).IsSome
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/NullableCsharpImportTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/NullableCsharpImportTests.fs
new file mode 100644
index 00000000000..60930ad56dd
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Language/NullableCsharpImportTests.fs
@@ -0,0 +1,85 @@
+module Language.NullableCSharpImport
+
+open FSharp.Test
+open Xunit
+open FSharp.Test.Compiler
+
+[]
+let ``Consumption of nullable C# - no generics, just strings in methods and fields`` () =
+    let csharpLib =
+        CSharp """
+    #nullable enable
+    namespace Nullables {
+        public class NullableClass {
+            // Fields with nullable type
+            public static string NotNullField;
+            // Fields with non-nullable type
+            public static string? MaybeNullField;
+            // Methods which return nullable string
+            public static string? ReturnsNullableStringNoParams() { return null; }
+            public static string? ReturnsNullableString1NullableParam(string? _) { return null; }
+            public static string? ReturnsNullableString1NonNullableParam(string _) { return null; }
+            public static string? ReturnsNullableString2NullableParams(string? _, string? __) { return null; }
+            public static string? ReturnsNullableString2NonNullableParams(string _, string __) { return null; }
+            public static string? ReturnsNullableString1Nullable1NonNullableParam(string? _, string __) { return null; }
+            
+            // Methods which return non-nullable string
+            public static string ReturnsNonNullableStringNoParams() { return ""; }
+            public static string ReturnsNonNullableString1NullableParam(string? _) { return ""; }
+            public static string ReturnsNonNullableString1NonNullableParam(string _) { return ""; }
+            public static string ReturnsNonNullableString2NullableParams(string? _, string? __) { return ""; }
+            public static string ReturnsNonNullableString2NonNullableParams(string _, string __) { return ""; }
+            public static string ReturnsNonNullableString1Nullable1NonNullableParam(string? _, string __) { return ""; }
+        }
+    }""" |> withName "csNullableLib"
+
+    FSharp """
+    module FSNullable
+    open Nullables
+    
+    let nullablestrNoParams : string = NullableClass.ReturnsNullableStringNoParams() // Error here, line 5
+    let nonNullableStrNoParams : string | null = NullableClass.ReturnsNonNullableStringNoParams()
+    let nullablestrNoParamsCorrectlyAnnotated : string | null = NullableClass.ReturnsNullableStringNoParams()
+    let nonNullableStrNoParamsCorrectlyAnnotated : string = NullableClass.ReturnsNonNullableStringNoParams()
+    let notNullField : string = NullableClass.NotNullField
+    let maybeNullField : string | null = NullableClass.MaybeNullField
+    let maybeNullField2 : string | null = NullableClass.NotNullField
+
+
+    let notNullField2 : string = NullableClass.MaybeNullField  // Error here, line 14
+    NullableClass.MaybeNullField <- null
+    NullableClass.NotNullField <- null  // Error here, line 16
+
+    let notNullArg : string = "hello"
+    let maybeNullArg : string | null = "there"
+
+    let nullableParamOk1 = NullableClass.ReturnsNullableString1NullableParam(notNullArg)
+    let nullableParamOk2 = NullableClass.ReturnsNullableString1NullableParam(maybeNullArg) 
+
+    let nonNullParamCallPass = NullableClass.ReturnsNullableString1NonNullableParam(notNullArg)
+    let nonNullParamCallFail = NullableClass.ReturnsNullableString1NonNullableParam(maybeNullArg) // Error here, 25
+
+    let mixedParams1 = NullableClass.ReturnsNullableString1Nullable1NonNullableParam(notNullArg,notNullArg)
+    let mixedParams2 = NullableClass.ReturnsNullableString1Nullable1NonNullableParam(maybeNullArg,maybeNullArg) // Error here, 28
+    let mixedParams3 = NullableClass.ReturnsNullableString1Nullable1NonNullableParam(maybeNullArg,notNullArg)
+    let mixedParams4 = NullableClass.ReturnsNullableString1Nullable1NonNullableParam(notNullArg,maybeNullArg) // Error here, 30
+
+
+    """
+    |> asLibrary
+    |> withLangVersionPreview
+    |> withReferences [csharpLib]
+    |> withCheckNulls
+    |> withWarnOn 3261
+    |> withOptions ["--warnaserror+"]
+    |> compile
+    |> shouldFail
+    |> withDiagnostics [
+            Error 3261, Line 5, Col 40, Line 5, Col 85, "Nullness warning: The types 'string' and 'string | null' do not have compatible nullability."
+            Error 3261, Line 5, Col 40, Line 5, Col 85, "Nullness warning: The types 'string' and 'string | null' do not have equivalent nullability."
+            Error 3261, Line 14, Col 34, Line 14, Col 62, "Nullness warning: The types 'string' and 'string | null' do not have equivalent nullability."
+            Error 3261, Line 16, Col 35, Line 16, Col 39, "Nullness warning: The type 'string' does not support 'null'."
+            Error 3261, Line 25, Col 85, Line 25, Col 97, "Nullness warning: The types 'string' and 'string | null' do not have equivalent nullability."
+            Error 3261, Line 28, Col 99, Line 28, Col 111, "Nullness warning: The types 'string' and 'string | null' do not have equivalent nullability."
+            Error 3261, Line 30, Col 97, Line 30, Col 109, "Nullness warning: The types 'string' and 'string | null' do not have equivalent nullability."]
+            
diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl
index 25a540db859..15b58c9aea1 100644
--- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl
+++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl
@@ -296,10 +296,30 @@ FSharp.Compiler.AbstractIL.IL+ILAttribute: Int32 get_Tag()
 FSharp.Compiler.AbstractIL.IL+ILAttribute: System.String ToString()
 FSharp.Compiler.AbstractIL.IL+ILAttributes: ILAttribute[] AsArray()
 FSharp.Compiler.AbstractIL.IL+ILAttributes: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILAttribute] AsList()
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Given: ILAttributes Item
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Given: ILAttributes get_Item()
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Reader: Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,FSharp.Compiler.AbstractIL.IL+ILAttribute[]] Item
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Reader: Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,FSharp.Compiler.AbstractIL.IL+ILAttribute[]] get_Item()
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Tags: Int32 Given
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Tags: Int32 Reader
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: Boolean IsGiven
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: Boolean IsReader
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: Boolean get_IsGiven()
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: Boolean get_IsReader()
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Given
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Reader
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Tags
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: ILAttributes GetCustomAttrs(Int32)
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: ILAttributesStored NewGiven(ILAttributes)
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: ILAttributesStored NewReader(Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,FSharp.Compiler.AbstractIL.IL+ILAttribute[]])
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: Int32 Tag
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: Int32 get_Tag()
 FSharp.Compiler.AbstractIL.IL+ILAttributesStored: System.String ToString()
 FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(ILCallingConv)
 FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(System.Object)
 FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean IsCallconv
+FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean get_IsCallconv()
 FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILArgConvention Item2
 FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILArgConvention get_Item2()
 FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILCallingConv Instance
@@ -390,10 +410,14 @@ FSharp.Compiler.AbstractIL.IL+ILEventDef: Boolean get_IsRTSpecialName()
 FSharp.Compiler.AbstractIL.IL+ILEventDef: Boolean get_IsSpecialName()
 FSharp.Compiler.AbstractIL.IL+ILEventDef: ILAttributes CustomAttrs
 FSharp.Compiler.AbstractIL.IL+ILEventDef: ILAttributes get_CustomAttrs()
+FSharp.Compiler.AbstractIL.IL+ILEventDef: ILAttributesStored CustomAttrsStored
+FSharp.Compiler.AbstractIL.IL+ILEventDef: ILAttributesStored get_CustomAttrsStored()
 FSharp.Compiler.AbstractIL.IL+ILEventDef: ILMethodRef AddMethod
 FSharp.Compiler.AbstractIL.IL+ILEventDef: ILMethodRef RemoveMethod
 FSharp.Compiler.AbstractIL.IL+ILEventDef: ILMethodRef get_AddMethod()
 FSharp.Compiler.AbstractIL.IL+ILEventDef: ILMethodRef get_RemoveMethod()
+FSharp.Compiler.AbstractIL.IL+ILEventDef: Int32 MetadataIndex
+FSharp.Compiler.AbstractIL.IL+ILEventDef: Int32 get_MetadataIndex()
 FSharp.Compiler.AbstractIL.IL+ILEventDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILMethodRef] OtherMethods
 FSharp.Compiler.AbstractIL.IL+ILEventDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILMethodRef] get_OtherMethods()
 FSharp.Compiler.AbstractIL.IL+ILEventDef: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILMethodRef] FireMethod
@@ -445,10 +469,14 @@ FSharp.Compiler.AbstractIL.IL+ILFieldDef: Boolean get_IsStatic()
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: Boolean get_NotSerialized()
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILAttributes CustomAttrs
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILAttributes get_CustomAttrs()
+FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILAttributesStored CustomAttrsStored
+FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILAttributesStored get_CustomAttrsStored()
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILMemberAccess Access
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILMemberAccess get_Access()
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILType FieldType
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILType get_FieldType()
+FSharp.Compiler.AbstractIL.IL+ILFieldDef: Int32 MetadataIndex
+FSharp.Compiler.AbstractIL.IL+ILFieldDef: Int32 get_MetadataIndex()
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILFieldInit] LiteralValue
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILFieldInit] get_LiteralValue()
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILNativeType] Marshal
@@ -762,6 +790,8 @@ FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean get_IsVirtual()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean get_IsZeroInit()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILAttributes CustomAttrs
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILAttributes get_CustomAttrs()
+FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILAttributesStored CustomAttrsStored
+FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILAttributesStored get_CustomAttrsStored()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILCallingConv CallingConv
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILCallingConv get_CallingConv()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILCallingSignature GetCallingSignature()
@@ -774,7 +804,9 @@ FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILReturn get_Return()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILSecurityDecls SecurityDecls
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILSecurityDecls get_SecurityDecls()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: Int32 MaxStack
+FSharp.Compiler.AbstractIL.IL+ILMethodDef: Int32 MetadataIndex
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: Int32 get_MaxStack()
+FSharp.Compiler.AbstractIL.IL+ILMethodDef: Int32 get_MetadataIndex()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: MethodBody Body
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: MethodBody get_Body()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef] GenericParams
@@ -1230,10 +1262,14 @@ FSharp.Compiler.AbstractIL.IL+ILPropertyDef: Boolean get_IsRTSpecialName()
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: Boolean get_IsSpecialName()
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILAttributes CustomAttrs
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILAttributes get_CustomAttrs()
+FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILAttributesStored CustomAttrsStored
+FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILAttributesStored get_CustomAttrsStored()
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILThisConvention CallingConv
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILThisConvention get_CallingConv()
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILType PropertyType
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILType get_PropertyType()
+FSharp.Compiler.AbstractIL.IL+ILPropertyDef: Int32 MetadataIndex
+FSharp.Compiler.AbstractIL.IL+ILPropertyDef: Int32 get_MetadataIndex()
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType] Args
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType] get_Args()
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILFieldInit] Init
@@ -1490,6 +1526,8 @@ FSharp.Compiler.AbstractIL.IL+ILTypeDef: Boolean get_IsStruct()
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: Boolean get_IsStructOrEnum()
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILAttributes CustomAttrs
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILAttributes get_CustomAttrs()
+FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILAttributesStored CustomAttrsStored
+FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILAttributesStored get_CustomAttrsStored()
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILDefaultPInvokeEncoding Encoding
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILDefaultPInvokeEncoding get_Encoding()
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILEventDefs Events
@@ -1511,6 +1549,8 @@ FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDefLayout Layout
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDefLayout get_Layout()
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDefs NestedTypes
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDefs get_NestedTypes()
+FSharp.Compiler.AbstractIL.IL+ILTypeDef: Int32 MetadataIndex
+FSharp.Compiler.AbstractIL.IL+ILTypeDef: Int32 get_MetadataIndex()
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef] GenericParams
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef] get_GenericParams()
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType] Implements
@@ -4231,6 +4271,8 @@ FSharp.Compiler.EditorServices.ToolTipElementData: Void .ctor(Microsoft.FSharp.C
 FSharp.Compiler.EditorServices.ToolTipText: Boolean Equals(FSharp.Compiler.EditorServices.ToolTipText)
 FSharp.Compiler.EditorServices.ToolTipText: Boolean Equals(System.Object)
 FSharp.Compiler.EditorServices.ToolTipText: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.EditorServices.ToolTipText: Boolean IsToolTipText
+FSharp.Compiler.EditorServices.ToolTipText: Boolean get_IsToolTipText()
 FSharp.Compiler.EditorServices.ToolTipText: FSharp.Compiler.EditorServices.ToolTipText NewToolTipText(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.EditorServices.ToolTipElement])
 FSharp.Compiler.EditorServices.ToolTipText: Int32 GetHashCode()
 FSharp.Compiler.EditorServices.ToolTipText: Int32 GetHashCode(System.Collections.IEqualityComparer)
@@ -4274,6 +4316,8 @@ FSharp.Compiler.EditorServices.XmlDocParser: Microsoft.FSharp.Collections.FSharp
 FSharp.Compiler.EditorServices.XmlDocable: Boolean Equals(FSharp.Compiler.EditorServices.XmlDocable)
 FSharp.Compiler.EditorServices.XmlDocable: Boolean Equals(System.Object)
 FSharp.Compiler.EditorServices.XmlDocable: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.EditorServices.XmlDocable: Boolean IsXmlDocable
+FSharp.Compiler.EditorServices.XmlDocable: Boolean get_IsXmlDocable()
 FSharp.Compiler.EditorServices.XmlDocable: FSharp.Compiler.EditorServices.XmlDocable NewXmlDocable(Int32, Int32, Microsoft.FSharp.Collections.FSharpList`1[System.String])
 FSharp.Compiler.EditorServices.XmlDocable: Int32 CompareTo(FSharp.Compiler.EditorServices.XmlDocable)
 FSharp.Compiler.EditorServices.XmlDocable: Int32 CompareTo(System.Object)
@@ -5298,21 +5342,25 @@ FSharp.Compiler.Symbols.FSharpSymbolPatterns: Microsoft.FSharp.Core.FSharpOption
 FSharp.Compiler.Symbols.FSharpSymbolPatterns: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Symbols.FSharpField,FSharp.Compiler.Symbols.FSharpType]] |Field|_|(FSharp.Compiler.Symbols.FSharpSymbol)
 FSharp.Compiler.Symbols.FSharpSymbolPatterns: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.Symbols.FSharpEntity,FSharp.Compiler.Symbols.FSharpEntity,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Symbols.FSharpType]]] |FSharpEntity|_|(FSharp.Compiler.Symbols.FSharpSymbol)
 FSharp.Compiler.Symbols.FSharpType: Boolean Equals(System.Object)
+FSharp.Compiler.Symbols.FSharpType: Boolean HasNullAnnotation
 FSharp.Compiler.Symbols.FSharpType: Boolean HasTypeDefinition
 FSharp.Compiler.Symbols.FSharpType: Boolean IsAbbreviation
 FSharp.Compiler.Symbols.FSharpType: Boolean IsAnonRecordType
 FSharp.Compiler.Symbols.FSharpType: Boolean IsFunctionType
 FSharp.Compiler.Symbols.FSharpType: Boolean IsGenericParameter
 FSharp.Compiler.Symbols.FSharpType: Boolean IsMeasureType
+FSharp.Compiler.Symbols.FSharpType: Boolean IsNullAmbivalent
 FSharp.Compiler.Symbols.FSharpType: Boolean IsStructTupleType
 FSharp.Compiler.Symbols.FSharpType: Boolean IsTupleType
 FSharp.Compiler.Symbols.FSharpType: Boolean IsUnresolved
+FSharp.Compiler.Symbols.FSharpType: Boolean get_HasNullAnnotation()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_HasTypeDefinition()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsAbbreviation()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsAnonRecordType()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsFunctionType()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsGenericParameter()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsMeasureType()
+FSharp.Compiler.Symbols.FSharpType: Boolean get_IsNullAmbivalent()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsStructTupleType()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsTupleType()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsUnresolved()
@@ -5508,6 +5556,8 @@ FSharp.Compiler.Syntax.DebugPointAtInOrTo: System.String ToString()
 FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean Equals(FSharp.Compiler.Syntax.DebugPointAtLeafExpr)
 FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean Equals(System.Object)
 FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean IsYes
+FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean get_IsYes()
 FSharp.Compiler.Syntax.DebugPointAtLeafExpr: FSharp.Compiler.Syntax.DebugPointAtLeafExpr NewYes(FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.DebugPointAtLeafExpr: FSharp.Compiler.Text.Range Item
 FSharp.Compiler.Syntax.DebugPointAtLeafExpr: FSharp.Compiler.Text.Range get_Item()
@@ -5642,6 +5692,8 @@ FSharp.Compiler.Syntax.Ident: System.String ToString()
 FSharp.Compiler.Syntax.Ident: System.String get_idText()
 FSharp.Compiler.Syntax.Ident: System.String idText
 FSharp.Compiler.Syntax.Ident: Void .ctor(System.String, FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.ParsedHashDirective: Boolean IsParsedHashDirective
+FSharp.Compiler.Syntax.ParsedHashDirective: Boolean get_IsParsedHashDirective()
 FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Syntax.ParsedHashDirective NewParsedHashDirective(System.String, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirectiveArgument], FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Text.Range get_range()
 FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Text.Range range
@@ -5680,6 +5732,8 @@ FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: FSharp.Compiler.Text.Range g
 FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: Int32 Tag
 FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: Int32 get_Tag()
 FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: System.String ToString()
+FSharp.Compiler.Syntax.ParsedImplFile: Boolean IsParsedImplFile
+FSharp.Compiler.Syntax.ParsedImplFile: Boolean get_IsParsedImplFile()
 FSharp.Compiler.Syntax.ParsedImplFile: FSharp.Compiler.Syntax.ParsedImplFile NewParsedImplFile(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirective], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedImplFileFragment])
 FSharp.Compiler.Syntax.ParsedImplFile: Int32 Tag
 FSharp.Compiler.Syntax.ParsedImplFile: Int32 get_Tag()
@@ -5731,9 +5785,11 @@ FSharp.Compiler.Syntax.ParsedImplFileFragment: Int32 get_Tag()
 FSharp.Compiler.Syntax.ParsedImplFileFragment: System.String ToString()
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsExe
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsLastCompiland
+FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsParsedImplFileInput
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsScript
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsExe()
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsLastCompiland()
+FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsParsedImplFileInput()
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsScript()
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_isScript()
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean isScript
@@ -5797,6 +5853,8 @@ FSharp.Compiler.Syntax.ParsedInput: Microsoft.FSharp.Collections.FSharpSet`1[Sys
 FSharp.Compiler.Syntax.ParsedInput: System.String FileName
 FSharp.Compiler.Syntax.ParsedInput: System.String ToString()
 FSharp.Compiler.Syntax.ParsedInput: System.String get_FileName()
+FSharp.Compiler.Syntax.ParsedScriptInteraction: Boolean IsDefinitions
+FSharp.Compiler.Syntax.ParsedScriptInteraction: Boolean get_IsDefinitions()
 FSharp.Compiler.Syntax.ParsedScriptInteraction: FSharp.Compiler.Syntax.ParsedScriptInteraction NewDefinitions(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl], FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.ParsedScriptInteraction: FSharp.Compiler.Text.Range get_range()
 FSharp.Compiler.Syntax.ParsedScriptInteraction: FSharp.Compiler.Text.Range range
@@ -5805,6 +5863,8 @@ FSharp.Compiler.Syntax.ParsedScriptInteraction: Int32 get_Tag()
 FSharp.Compiler.Syntax.ParsedScriptInteraction: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl] defns
 FSharp.Compiler.Syntax.ParsedScriptInteraction: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl] get_defns()
 FSharp.Compiler.Syntax.ParsedScriptInteraction: System.String ToString()
+FSharp.Compiler.Syntax.ParsedSigFile: Boolean IsParsedSigFile
+FSharp.Compiler.Syntax.ParsedSigFile: Boolean get_IsParsedSigFile()
 FSharp.Compiler.Syntax.ParsedSigFile: FSharp.Compiler.Syntax.ParsedSigFile NewParsedSigFile(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirective], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedSigFileFragment])
 FSharp.Compiler.Syntax.ParsedSigFile: Int32 Tag
 FSharp.Compiler.Syntax.ParsedSigFile: Int32 get_Tag()
@@ -5854,6 +5914,8 @@ FSharp.Compiler.Syntax.ParsedSigFileFragment: FSharp.Compiler.Syntax.ParsedSigFi
 FSharp.Compiler.Syntax.ParsedSigFileFragment: Int32 Tag
 FSharp.Compiler.Syntax.ParsedSigFileFragment: Int32 get_Tag()
 FSharp.Compiler.Syntax.ParsedSigFileFragment: System.String ToString()
+FSharp.Compiler.Syntax.ParsedSigFileInput: Boolean IsParsedSigFileInput
+FSharp.Compiler.Syntax.ParsedSigFileInput: Boolean get_IsParsedSigFileInput()
 FSharp.Compiler.Syntax.ParsedSigFileInput: FSharp.Compiler.Syntax.ParsedSigFileInput NewParsedSigFileInput(System.String, FSharp.Compiler.Syntax.QualifiedNameOfFile, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ScopedPragma], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirective], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleOrNamespaceSig], FSharp.Compiler.SyntaxTrivia.ParsedSigFileInputTrivia, Microsoft.FSharp.Collections.FSharpSet`1[System.String])
 FSharp.Compiler.Syntax.ParsedSigFileInput: FSharp.Compiler.Syntax.QualifiedNameOfFile QualifiedName
 FSharp.Compiler.Syntax.ParsedSigFileInput: FSharp.Compiler.Syntax.QualifiedNameOfFile get_QualifiedName()
@@ -5926,6 +5988,8 @@ FSharp.Compiler.Syntax.PrettyNaming: System.String FormatAndOtherOverloadsString
 FSharp.Compiler.Syntax.PrettyNaming: System.String FsiDynamicModulePrefix
 FSharp.Compiler.Syntax.PrettyNaming: System.String NormalizeIdentifierBackticks(System.String)
 FSharp.Compiler.Syntax.PrettyNaming: System.String get_FsiDynamicModulePrefix()
+FSharp.Compiler.Syntax.QualifiedNameOfFile: Boolean IsQualifiedNameOfFile
+FSharp.Compiler.Syntax.QualifiedNameOfFile: Boolean get_IsQualifiedNameOfFile()
 FSharp.Compiler.Syntax.QualifiedNameOfFile: FSharp.Compiler.Syntax.Ident Id
 FSharp.Compiler.Syntax.QualifiedNameOfFile: FSharp.Compiler.Syntax.Ident Item
 FSharp.Compiler.Syntax.QualifiedNameOfFile: FSharp.Compiler.Syntax.Ident get_Id()
@@ -5941,6 +6005,8 @@ FSharp.Compiler.Syntax.QualifiedNameOfFile: System.String get_Text()
 FSharp.Compiler.Syntax.ScopedPragma: Boolean Equals(FSharp.Compiler.Syntax.ScopedPragma)
 FSharp.Compiler.Syntax.ScopedPragma: Boolean Equals(System.Object)
 FSharp.Compiler.Syntax.ScopedPragma: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.Syntax.ScopedPragma: Boolean IsWarningOff
+FSharp.Compiler.Syntax.ScopedPragma: Boolean get_IsWarningOff()
 FSharp.Compiler.Syntax.ScopedPragma: FSharp.Compiler.Syntax.ScopedPragma NewWarningOff(FSharp.Compiler.Text.Range, Int32)
 FSharp.Compiler.Syntax.ScopedPragma: FSharp.Compiler.Text.Range get_range()
 FSharp.Compiler.Syntax.ScopedPragma: FSharp.Compiler.Text.Range range
@@ -5954,7 +6020,9 @@ FSharp.Compiler.Syntax.ScopedPragma: System.String ToString()
 FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(FSharp.Compiler.Syntax.SeqExprOnly)
 FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(System.Object)
 FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.Syntax.SeqExprOnly: Boolean IsSeqExprOnly
 FSharp.Compiler.Syntax.SeqExprOnly: Boolean Item
+FSharp.Compiler.Syntax.SeqExprOnly: Boolean get_IsSeqExprOnly()
 FSharp.Compiler.Syntax.SeqExprOnly: Boolean get_Item()
 FSharp.Compiler.Syntax.SeqExprOnly: FSharp.Compiler.Syntax.SeqExprOnly NewSeqExprOnly(Boolean)
 FSharp.Compiler.Syntax.SeqExprOnly: Int32 CompareTo(FSharp.Compiler.Syntax.SeqExprOnly)
@@ -5997,6 +6065,8 @@ FSharp.Compiler.Syntax.SynAccess: Int32 GetHashCode(System.Collections.IEquality
 FSharp.Compiler.Syntax.SynAccess: Int32 Tag
 FSharp.Compiler.Syntax.SynAccess: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynAccess: System.String ToString()
+FSharp.Compiler.Syntax.SynArgInfo: Boolean IsSynArgInfo
+FSharp.Compiler.Syntax.SynArgInfo: Boolean get_IsSynArgInfo()
 FSharp.Compiler.Syntax.SynArgInfo: Boolean get_optional()
 FSharp.Compiler.Syntax.SynArgInfo: Boolean optional
 FSharp.Compiler.Syntax.SynArgInfo: FSharp.Compiler.Syntax.SynArgInfo NewSynArgInfo(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident])
@@ -6053,6 +6123,8 @@ FSharp.Compiler.Syntax.SynAttributeList: Microsoft.FSharp.Collections.FSharpList
 FSharp.Compiler.Syntax.SynAttributeList: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttribute] get_Attributes()
 FSharp.Compiler.Syntax.SynAttributeList: System.String ToString()
 FSharp.Compiler.Syntax.SynAttributeList: Void .ctor(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttribute], FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynBinding: Boolean IsSynBinding
+FSharp.Compiler.Syntax.SynBinding: Boolean get_IsSynBinding()
 FSharp.Compiler.Syntax.SynBinding: Boolean get_isInline()
 FSharp.Compiler.Syntax.SynBinding: Boolean get_isMutable()
 FSharp.Compiler.Syntax.SynBinding: Boolean isInline
@@ -6116,6 +6188,8 @@ FSharp.Compiler.Syntax.SynBindingKind: Int32 GetHashCode(System.Collections.IEqu
 FSharp.Compiler.Syntax.SynBindingKind: Int32 Tag
 FSharp.Compiler.Syntax.SynBindingKind: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynBindingKind: System.String ToString()
+FSharp.Compiler.Syntax.SynBindingReturnInfo: Boolean IsSynBindingReturnInfo
+FSharp.Compiler.Syntax.SynBindingReturnInfo: Boolean get_IsSynBindingReturnInfo()
 FSharp.Compiler.Syntax.SynBindingReturnInfo: FSharp.Compiler.Syntax.SynBindingReturnInfo NewSynBindingReturnInfo(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.SyntaxTrivia.SynBindingReturnInfoTrivia)
 FSharp.Compiler.Syntax.SynBindingReturnInfo: FSharp.Compiler.Syntax.SynType get_typeName()
 FSharp.Compiler.Syntax.SynBindingReturnInfo: FSharp.Compiler.Syntax.SynType typeName
@@ -6150,6 +6224,8 @@ FSharp.Compiler.Syntax.SynByteStringKind: Int32 GetHashCode(System.Collections.I
 FSharp.Compiler.Syntax.SynByteStringKind: Int32 Tag
 FSharp.Compiler.Syntax.SynByteStringKind: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynByteStringKind: System.String ToString()
+FSharp.Compiler.Syntax.SynComponentInfo: Boolean IsSynComponentInfo
+FSharp.Compiler.Syntax.SynComponentInfo: Boolean get_IsSynComponentInfo()
 FSharp.Compiler.Syntax.SynComponentInfo: Boolean get_preferPostfix()
 FSharp.Compiler.Syntax.SynComponentInfo: Boolean preferPostfix
 FSharp.Compiler.Syntax.SynComponentInfo: FSharp.Compiler.Syntax.SynComponentInfo NewSynComponentInfo(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynTyparDecls], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynTypeConstraint], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Xml.PreXmlDoc, Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range)
@@ -6349,6 +6425,8 @@ FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Text.Range Range(FSharp.Compile
 FSharp.Compiler.Syntax.SynConst: Int32 Tag
 FSharp.Compiler.Syntax.SynConst: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynConst: System.String ToString()
+FSharp.Compiler.Syntax.SynEnumCase: Boolean IsSynEnumCase
+FSharp.Compiler.Syntax.SynEnumCase: Boolean get_IsSynEnumCase()
 FSharp.Compiler.Syntax.SynEnumCase: FSharp.Compiler.Syntax.SynEnumCase NewSynEnumCase(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynIdent, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynEnumCaseTrivia)
 FSharp.Compiler.Syntax.SynEnumCase: FSharp.Compiler.Syntax.SynExpr get_valueExpr()
 FSharp.Compiler.Syntax.SynEnumCase: FSharp.Compiler.Syntax.SynExpr valueExpr
@@ -6367,6 +6445,8 @@ 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.SynExceptionDefn: Boolean IsSynExceptionDefn
+FSharp.Compiler.Syntax.SynExceptionDefn: Boolean get_IsSynExceptionDefn()
 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
 FSharp.Compiler.Syntax.SynExceptionDefn: FSharp.Compiler.Syntax.SynExceptionDefnRepr get_exnRepr()
@@ -6381,6 +6461,8 @@ FSharp.Compiler.Syntax.SynExceptionDefn: Microsoft.FSharp.Collections.FSharpList
 FSharp.Compiler.Syntax.SynExceptionDefn: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_withKeyword()
 FSharp.Compiler.Syntax.SynExceptionDefn: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] withKeyword
 FSharp.Compiler.Syntax.SynExceptionDefn: System.String ToString()
+FSharp.Compiler.Syntax.SynExceptionDefnRepr: Boolean IsSynExceptionDefnRepr
+FSharp.Compiler.Syntax.SynExceptionDefnRepr: Boolean get_IsSynExceptionDefnRepr()
 FSharp.Compiler.Syntax.SynExceptionDefnRepr: FSharp.Compiler.Syntax.SynExceptionDefnRepr NewSynExceptionDefnRepr(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynUnionCase, Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident]], FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynExceptionDefnRepr: FSharp.Compiler.Syntax.SynUnionCase caseName
 FSharp.Compiler.Syntax.SynExceptionDefnRepr: FSharp.Compiler.Syntax.SynUnionCase get_caseName()
@@ -6399,6 +6481,8 @@ FSharp.Compiler.Syntax.SynExceptionDefnRepr: Microsoft.FSharp.Core.FSharpOption`
 FSharp.Compiler.Syntax.SynExceptionDefnRepr: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident]] get_longId()
 FSharp.Compiler.Syntax.SynExceptionDefnRepr: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident]] longId
 FSharp.Compiler.Syntax.SynExceptionDefnRepr: System.String ToString()
+FSharp.Compiler.Syntax.SynExceptionSig: Boolean IsSynExceptionSig
+FSharp.Compiler.Syntax.SynExceptionSig: Boolean get_IsSynExceptionSig()
 FSharp.Compiler.Syntax.SynExceptionSig: FSharp.Compiler.Syntax.SynExceptionDefnRepr exnRepr
 FSharp.Compiler.Syntax.SynExceptionSig: FSharp.Compiler.Syntax.SynExceptionDefnRepr get_exnRepr()
 FSharp.Compiler.Syntax.SynExceptionSig: FSharp.Compiler.Syntax.SynExceptionSig NewSynExceptionSig(FSharp.Compiler.Syntax.SynExceptionDefnRepr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberSig], FSharp.Compiler.Text.Range)
@@ -7333,6 +7417,8 @@ FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Text.Range get_RangeWithoutAnyEx
 FSharp.Compiler.Syntax.SynExpr: Int32 Tag
 FSharp.Compiler.Syntax.SynExpr: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynExpr: System.String ToString()
+FSharp.Compiler.Syntax.SynExprAndBang: Boolean IsSynExprAndBang
+FSharp.Compiler.Syntax.SynExprAndBang: Boolean get_IsSynExprAndBang()
 FSharp.Compiler.Syntax.SynExprAndBang: Boolean get_isFromSource()
 FSharp.Compiler.Syntax.SynExprAndBang: Boolean get_isUse()
 FSharp.Compiler.Syntax.SynExprAndBang: Boolean isFromSource
@@ -7351,6 +7437,8 @@ FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Text.Range range
 FSharp.Compiler.Syntax.SynExprAndBang: Int32 Tag
 FSharp.Compiler.Syntax.SynExprAndBang: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynExprAndBang: System.String ToString()
+FSharp.Compiler.Syntax.SynExprRecordField: Boolean IsSynExprRecordField
+FSharp.Compiler.Syntax.SynExprRecordField: Boolean get_IsSynExprRecordField()
 FSharp.Compiler.Syntax.SynExprRecordField: FSharp.Compiler.Syntax.SynExprRecordField NewSynExprRecordField(System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr], Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]])
 FSharp.Compiler.Syntax.SynExprRecordField: Int32 Tag
 FSharp.Compiler.Syntax.SynExprRecordField: Int32 get_Tag()
@@ -7363,6 +7451,8 @@ FSharp.Compiler.Syntax.SynExprRecordField: Microsoft.FSharp.Core.FSharpOption`1[
 FSharp.Compiler.Syntax.SynExprRecordField: System.String ToString()
 FSharp.Compiler.Syntax.SynExprRecordField: System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean] fieldName
 FSharp.Compiler.Syntax.SynExprRecordField: System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean] get_fieldName()
+FSharp.Compiler.Syntax.SynField: Boolean IsSynField
+FSharp.Compiler.Syntax.SynField: Boolean get_IsSynField()
 FSharp.Compiler.Syntax.SynField: Boolean get_isMutable()
 FSharp.Compiler.Syntax.SynField: Boolean get_isStatic()
 FSharp.Compiler.Syntax.SynField: Boolean isMutable
@@ -7387,6 +7477,8 @@ FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Com
 FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] accessibility
 FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] get_accessibility()
 FSharp.Compiler.Syntax.SynField: System.String ToString()
+FSharp.Compiler.Syntax.SynIdent: Boolean IsSynIdent
+FSharp.Compiler.Syntax.SynIdent: Boolean get_IsSynIdent()
 FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.Ident get_ident()
 FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.Ident ident
 FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.SynIdent NewSynIdent(FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia])
@@ -7395,6 +7487,8 @@ FSharp.Compiler.Syntax.SynIdent: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia] get_trivia()
 FSharp.Compiler.Syntax.SynIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia] trivia
 FSharp.Compiler.Syntax.SynIdent: System.String ToString()
+FSharp.Compiler.Syntax.SynInterfaceImpl: Boolean IsSynInterfaceImpl
+FSharp.Compiler.Syntax.SynInterfaceImpl: Boolean get_IsSynInterfaceImpl()
 FSharp.Compiler.Syntax.SynInterfaceImpl: FSharp.Compiler.Syntax.SynInterfaceImpl NewSynInterfaceImpl(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynBinding], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn], FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynInterfaceImpl: FSharp.Compiler.Syntax.SynType get_interfaceTy()
 FSharp.Compiler.Syntax.SynInterfaceImpl: FSharp.Compiler.Syntax.SynType interfaceTy
@@ -7431,7 +7525,9 @@ FSharp.Compiler.Syntax.SynInterpolatedStringPart: FSharp.Compiler.Syntax.SynInte
 FSharp.Compiler.Syntax.SynInterpolatedStringPart: Int32 Tag
 FSharp.Compiler.Syntax.SynInterpolatedStringPart: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynInterpolatedStringPart: System.String ToString()
+FSharp.Compiler.Syntax.SynLongIdent: Boolean IsSynLongIdent
 FSharp.Compiler.Syntax.SynLongIdent: Boolean ThereIsAnExtraDotAtTheEnd
+FSharp.Compiler.Syntax.SynLongIdent: Boolean get_IsSynLongIdent()
 FSharp.Compiler.Syntax.SynLongIdent: Boolean get_ThereIsAnExtraDotAtTheEnd()
 FSharp.Compiler.Syntax.SynLongIdent: FSharp.Compiler.Syntax.SynLongIdent NewSynLongIdent(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia]])
 FSharp.Compiler.Syntax.SynLongIdent: FSharp.Compiler.Text.Range Range
@@ -7457,6 +7553,8 @@ FSharp.Compiler.Syntax.SynLongIdent: Microsoft.FSharp.Collections.FSharpList`1[M
 FSharp.Compiler.Syntax.SynLongIdent: System.String ToString()
 FSharp.Compiler.Syntax.SynLongIdentHelpers: FSharp.Compiler.Syntax.SynLongIdent LongIdentWithDots(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range])
 FSharp.Compiler.Syntax.SynLongIdentHelpers: System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident],Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range]] |LongIdentWithDots|(FSharp.Compiler.Syntax.SynLongIdent)
+FSharp.Compiler.Syntax.SynMatchClause: Boolean IsSynMatchClause
+FSharp.Compiler.Syntax.SynMatchClause: Boolean get_IsSynMatchClause()
 FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.DebugPointAtTarget debugPoint
 FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.DebugPointAtTarget get_debugPoint()
 FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.SynExpr get_resultExpr()
@@ -7954,6 +8052,8 @@ FSharp.Compiler.Syntax.SynModuleDecl: FSharp.Compiler.Text.Range get_Range()
 FSharp.Compiler.Syntax.SynModuleDecl: Int32 Tag
 FSharp.Compiler.Syntax.SynModuleDecl: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynModuleDecl: System.String ToString()
+FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean IsSynModuleOrNamespace
+FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean get_IsSynModuleOrNamespace()
 FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean get_isRecursive()
 FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean isRecursive
 FSharp.Compiler.Syntax.SynModuleOrNamespace: FSharp.Compiler.Syntax.SynModuleOrNamespace NewSynModuleOrNamespace(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], Boolean, FSharp.Compiler.Syntax.SynModuleOrNamespaceKind, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl], FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynModuleOrNamespaceTrivia)
@@ -8012,6 +8112,8 @@ FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: Int32 GetHashCode(System.Collec
 FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: Int32 Tag
 FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: System.String ToString()
+FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean IsSynModuleOrNamespaceSig
+FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean get_IsSynModuleOrNamespaceSig()
 FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean get_isRecursive()
 FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean isRecursive
 FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: FSharp.Compiler.Syntax.SynModuleOrNamespaceKind get_kind()
@@ -8412,6 +8514,8 @@ FSharp.Compiler.Syntax.SynRationalConst: FSharp.Compiler.Syntax.SynRationalConst
 FSharp.Compiler.Syntax.SynRationalConst: Int32 Tag
 FSharp.Compiler.Syntax.SynRationalConst: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynRationalConst: System.String ToString()
+FSharp.Compiler.Syntax.SynReturnInfo: Boolean IsSynReturnInfo
+FSharp.Compiler.Syntax.SynReturnInfo: Boolean get_IsSynReturnInfo()
 FSharp.Compiler.Syntax.SynReturnInfo: FSharp.Compiler.Syntax.SynReturnInfo NewSynReturnInfo(System.Tuple`2[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Syntax.SynArgInfo], FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynReturnInfo: FSharp.Compiler.Text.Range Range
 FSharp.Compiler.Syntax.SynReturnInfo: FSharp.Compiler.Text.Range get_Range()
@@ -8485,6 +8589,8 @@ FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: FSharp.Compiler.Syntax.Syn
 FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: Int32 Tag
 FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: System.String ToString()
+FSharp.Compiler.Syntax.SynSimplePats: Boolean IsSimplePats
+FSharp.Compiler.Syntax.SynSimplePats: Boolean get_IsSimplePats()
 FSharp.Compiler.Syntax.SynSimplePats: FSharp.Compiler.Syntax.SynSimplePats NewSimplePats(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynSimplePat], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range], FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynSimplePats: FSharp.Compiler.Text.Range Range
 FSharp.Compiler.Syntax.SynSimplePats: FSharp.Compiler.Text.Range get_Range()
@@ -8575,6 +8681,8 @@ FSharp.Compiler.Syntax.SynTupleTypeSegment: FSharp.Compiler.Text.Range get_Range
 FSharp.Compiler.Syntax.SynTupleTypeSegment: Int32 Tag
 FSharp.Compiler.Syntax.SynTupleTypeSegment: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynTupleTypeSegment: System.String ToString()
+FSharp.Compiler.Syntax.SynTypar: Boolean IsSynTypar
+FSharp.Compiler.Syntax.SynTypar: Boolean get_IsSynTypar()
 FSharp.Compiler.Syntax.SynTypar: Boolean get_isCompGen()
 FSharp.Compiler.Syntax.SynTypar: Boolean isCompGen
 FSharp.Compiler.Syntax.SynTypar: FSharp.Compiler.Syntax.Ident get_ident()
@@ -8587,6 +8695,8 @@ FSharp.Compiler.Syntax.SynTypar: FSharp.Compiler.Text.Range get_Range()
 FSharp.Compiler.Syntax.SynTypar: Int32 Tag
 FSharp.Compiler.Syntax.SynTypar: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynTypar: System.String ToString()
+FSharp.Compiler.Syntax.SynTyparDecl: Boolean IsSynTyparDecl
+FSharp.Compiler.Syntax.SynTyparDecl: Boolean get_IsSynTyparDecl()
 FSharp.Compiler.Syntax.SynTyparDecl: FSharp.Compiler.Syntax.SynTypar get_typar()
 FSharp.Compiler.Syntax.SynTyparDecl: FSharp.Compiler.Syntax.SynTypar typar
 FSharp.Compiler.Syntax.SynTyparDecl: FSharp.Compiler.Syntax.SynTyparDecl NewSynTyparDecl(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynTypar, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynType], FSharp.Compiler.SyntaxTrivia.SynTyparDeclTrivia)
@@ -8746,6 +8856,8 @@ FSharp.Compiler.Syntax.SynType+StaticConstantNamed: FSharp.Compiler.Syntax.SynTy
 FSharp.Compiler.Syntax.SynType+StaticConstantNamed: FSharp.Compiler.Syntax.SynType value
 FSharp.Compiler.Syntax.SynType+StaticConstantNamed: FSharp.Compiler.Text.Range get_range()
 FSharp.Compiler.Syntax.SynType+StaticConstantNamed: FSharp.Compiler.Text.Range range
+FSharp.Compiler.Syntax.SynType+StaticConstantNull: FSharp.Compiler.Text.Range get_range()
+FSharp.Compiler.Syntax.SynType+StaticConstantNull: FSharp.Compiler.Text.Range range
 FSharp.Compiler.Syntax.SynType+Tags: Int32 Anon
 FSharp.Compiler.Syntax.SynType+Tags: Int32 AnonRecd
 FSharp.Compiler.Syntax.SynType+Tags: Int32 App
@@ -8763,9 +8875,11 @@ FSharp.Compiler.Syntax.SynType+Tags: Int32 SignatureParameter
 FSharp.Compiler.Syntax.SynType+Tags: Int32 StaticConstant
 FSharp.Compiler.Syntax.SynType+Tags: Int32 StaticConstantExpr
 FSharp.Compiler.Syntax.SynType+Tags: Int32 StaticConstantNamed
+FSharp.Compiler.Syntax.SynType+Tags: Int32 StaticConstantNull
 FSharp.Compiler.Syntax.SynType+Tags: Int32 Tuple
 FSharp.Compiler.Syntax.SynType+Tags: Int32 Var
 FSharp.Compiler.Syntax.SynType+Tags: Int32 WithGlobalConstraints
+FSharp.Compiler.Syntax.SynType+Tags: Int32 WithNull
 FSharp.Compiler.Syntax.SynType+Tuple: Boolean get_isStruct()
 FSharp.Compiler.Syntax.SynType+Tuple: Boolean isStruct
 FSharp.Compiler.Syntax.SynType+Tuple: FSharp.Compiler.Text.Range get_range()
@@ -8782,6 +8896,12 @@ FSharp.Compiler.Syntax.SynType+WithGlobalConstraints: FSharp.Compiler.Text.Range
 FSharp.Compiler.Syntax.SynType+WithGlobalConstraints: FSharp.Compiler.Text.Range range
 FSharp.Compiler.Syntax.SynType+WithGlobalConstraints: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynTypeConstraint] constraints
 FSharp.Compiler.Syntax.SynType+WithGlobalConstraints: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynTypeConstraint] get_constraints()
+FSharp.Compiler.Syntax.SynType+WithNull: Boolean ambivalent
+FSharp.Compiler.Syntax.SynType+WithNull: Boolean get_ambivalent()
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Syntax.SynType get_innerType()
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Syntax.SynType innerType
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Text.Range get_range()
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Text.Range range
 FSharp.Compiler.Syntax.SynType: Boolean IsAnon
 FSharp.Compiler.Syntax.SynType: Boolean IsAnonRecd
 FSharp.Compiler.Syntax.SynType: Boolean IsApp
@@ -8799,9 +8919,11 @@ FSharp.Compiler.Syntax.SynType: Boolean IsSignatureParameter
 FSharp.Compiler.Syntax.SynType: Boolean IsStaticConstant
 FSharp.Compiler.Syntax.SynType: Boolean IsStaticConstantExpr
 FSharp.Compiler.Syntax.SynType: Boolean IsStaticConstantNamed
+FSharp.Compiler.Syntax.SynType: Boolean IsStaticConstantNull
 FSharp.Compiler.Syntax.SynType: Boolean IsTuple
 FSharp.Compiler.Syntax.SynType: Boolean IsVar
 FSharp.Compiler.Syntax.SynType: Boolean IsWithGlobalConstraints
+FSharp.Compiler.Syntax.SynType: Boolean IsWithNull
 FSharp.Compiler.Syntax.SynType: Boolean get_IsAnon()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsAnonRecd()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsApp()
@@ -8819,9 +8941,11 @@ FSharp.Compiler.Syntax.SynType: Boolean get_IsSignatureParameter()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsStaticConstant()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsStaticConstantExpr()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsStaticConstantNamed()
+FSharp.Compiler.Syntax.SynType: Boolean get_IsStaticConstantNull()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsTuple()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsVar()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsWithGlobalConstraints()
+FSharp.Compiler.Syntax.SynType: Boolean get_IsWithNull()
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewAnon(FSharp.Compiler.Text.Range)
 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)
@@ -8839,9 +8963,11 @@ FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewSignatureParam
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewStaticConstant(FSharp.Compiler.Syntax.SynConst, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewStaticConstantExpr(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewStaticConstantNamed(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewStaticConstantNull(FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewTuple(Boolean, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynTupleTypeSegment], FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewVar(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewWithGlobalConstraints(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynTypeConstraint], FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewWithNull(FSharp.Compiler.Syntax.SynType, Boolean, FSharp.Compiler.Text.Range)
 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
@@ -8859,10 +8985,12 @@ FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+SignatureParamete
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+StaticConstant
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+StaticConstantExpr
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+StaticConstantNamed
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+StaticConstantNull
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+Tags
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+Tuple
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+Var
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+WithGlobalConstraints
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+WithNull
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Text.Range Range
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Text.Range get_Range()
 FSharp.Compiler.Syntax.SynType: Int32 Tag
@@ -8877,6 +9005,7 @@ FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparIsEquatable
 FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparIsReferenceType
 FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparIsUnmanaged
 FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparIsValueType
+FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparNotSupportsNull
 FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparSubtypeOfType
 FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparSupportsMember
 FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparSupportsNull
@@ -8922,6 +9051,10 @@ FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparIsValueType: FSharp.Compiler.
 FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparIsValueType: FSharp.Compiler.Syntax.SynTypar typar
 FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparIsValueType: FSharp.Compiler.Text.Range get_range()
 FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparIsValueType: FSharp.Compiler.Text.Range range
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Syntax.SynTypar genericName
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Syntax.SynTypar get_genericName()
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Text.Range get_range()
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Text.Range range
 FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparSubtypeOfType: FSharp.Compiler.Syntax.SynTypar get_typar()
 FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparSubtypeOfType: FSharp.Compiler.Syntax.SynTypar typar
 FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparSubtypeOfType: FSharp.Compiler.Syntax.SynType get_typeName()
@@ -8947,6 +9080,7 @@ FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparIsEquatable
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparIsReferenceType
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparIsUnmanaged
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparIsValueType
+FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparNotSupportsNull
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparSubtypeOfType
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparSupportsMember
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparSupportsNull
@@ -8959,6 +9093,7 @@ FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparIsEquatable()
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparIsReferenceType()
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparIsUnmanaged()
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparIsValueType()
+FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparNotSupportsNull()
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparSubtypeOfType()
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparSupportsMember()
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparSupportsNull()
@@ -8971,6 +9106,7 @@ FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstrai
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparIsReferenceType(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparIsUnmanaged(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparIsValueType(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparNotSupportsNull(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparSubtypeOfType(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparSupportsMember(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynMemberSig, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparSupportsNull(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
@@ -8984,6 +9120,7 @@ FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstrai
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparIsReferenceType
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparIsUnmanaged
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparIsValueType
+FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparSubtypeOfType
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparSupportsMember
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparSupportsNull
@@ -8992,6 +9129,8 @@ FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Text.Range get_Range()
 FSharp.Compiler.Syntax.SynTypeConstraint: Int32 Tag
 FSharp.Compiler.Syntax.SynTypeConstraint: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynTypeConstraint: System.String ToString()
+FSharp.Compiler.Syntax.SynTypeDefn: Boolean IsSynTypeDefn
+FSharp.Compiler.Syntax.SynTypeDefn: Boolean get_IsSynTypeDefn()
 FSharp.Compiler.Syntax.SynTypeDefn: FSharp.Compiler.Syntax.SynComponentInfo get_typeInfo()
 FSharp.Compiler.Syntax.SynTypeDefn: FSharp.Compiler.Syntax.SynComponentInfo typeInfo
 FSharp.Compiler.Syntax.SynTypeDefn: FSharp.Compiler.Syntax.SynTypeDefn NewSynTypeDefn(FSharp.Compiler.Syntax.SynComponentInfo, FSharp.Compiler.Syntax.SynTypeDefnRepr, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberDefn], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynTypeDefnTrivia)
@@ -9108,6 +9247,8 @@ FSharp.Compiler.Syntax.SynTypeDefnRepr: FSharp.Compiler.Text.Range get_Range()
 FSharp.Compiler.Syntax.SynTypeDefnRepr: Int32 Tag
 FSharp.Compiler.Syntax.SynTypeDefnRepr: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynTypeDefnRepr: System.String ToString()
+FSharp.Compiler.Syntax.SynTypeDefnSig: Boolean IsSynTypeDefnSig
+FSharp.Compiler.Syntax.SynTypeDefnSig: Boolean get_IsSynTypeDefnSig()
 FSharp.Compiler.Syntax.SynTypeDefnSig: FSharp.Compiler.Syntax.SynComponentInfo get_typeInfo()
 FSharp.Compiler.Syntax.SynTypeDefnSig: FSharp.Compiler.Syntax.SynComponentInfo typeInfo
 FSharp.Compiler.Syntax.SynTypeDefnSig: FSharp.Compiler.Syntax.SynTypeDefnSig NewSynTypeDefnSig(FSharp.Compiler.Syntax.SynComponentInfo, FSharp.Compiler.Syntax.SynTypeDefnSigRepr, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberSig], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynTypeDefnSigTrivia)
@@ -9249,6 +9390,8 @@ FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Text.Range get_Ran
 FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: Int32 Tag
 FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: System.String ToString()
+FSharp.Compiler.Syntax.SynUnionCase: Boolean IsSynUnionCase
+FSharp.Compiler.Syntax.SynUnionCase: Boolean get_IsSynUnionCase()
 FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynIdent get_ident()
 FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynIdent ident
 FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynUnionCase NewSynUnionCase(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynIdent, FSharp.Compiler.Syntax.SynUnionCaseKind, FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynUnionCaseTrivia)
@@ -9289,6 +9432,8 @@ FSharp.Compiler.Syntax.SynUnionCaseKind: FSharp.Compiler.Syntax.SynUnionCaseKind
 FSharp.Compiler.Syntax.SynUnionCaseKind: Int32 Tag
 FSharp.Compiler.Syntax.SynUnionCaseKind: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynUnionCaseKind: System.String ToString()
+FSharp.Compiler.Syntax.SynValData: Boolean IsSynValData
+FSharp.Compiler.Syntax.SynValData: Boolean get_IsSynValData()
 FSharp.Compiler.Syntax.SynValData: FSharp.Compiler.Syntax.SynValData NewSynValData(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberFlags], FSharp.Compiler.Syntax.SynValInfo, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident])
 FSharp.Compiler.Syntax.SynValData: FSharp.Compiler.Syntax.SynValInfo SynValInfo
 FSharp.Compiler.Syntax.SynValData: FSharp.Compiler.Syntax.SynValInfo get_SynValInfo()
@@ -9301,6 +9446,8 @@ FSharp.Compiler.Syntax.SynValData: Microsoft.FSharp.Core.FSharpOption`1[FSharp.C
 FSharp.Compiler.Syntax.SynValData: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberFlags] get_memberFlags()
 FSharp.Compiler.Syntax.SynValData: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberFlags] memberFlags
 FSharp.Compiler.Syntax.SynValData: System.String ToString()
+FSharp.Compiler.Syntax.SynValInfo: Boolean IsSynValInfo
+FSharp.Compiler.Syntax.SynValInfo: Boolean get_IsSynValInfo()
 FSharp.Compiler.Syntax.SynValInfo: FSharp.Compiler.Syntax.SynArgInfo get_returnInfo()
 FSharp.Compiler.Syntax.SynValInfo: FSharp.Compiler.Syntax.SynArgInfo returnInfo
 FSharp.Compiler.Syntax.SynValInfo: FSharp.Compiler.Syntax.SynValInfo NewSynValInfo(Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynArgInfo]], FSharp.Compiler.Syntax.SynArgInfo)
@@ -9313,6 +9460,8 @@ FSharp.Compiler.Syntax.SynValInfo: Microsoft.FSharp.Collections.FSharpList`1[Mic
 FSharp.Compiler.Syntax.SynValInfo: Microsoft.FSharp.Collections.FSharpList`1[System.String] ArgNames
 FSharp.Compiler.Syntax.SynValInfo: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_ArgNames()
 FSharp.Compiler.Syntax.SynValInfo: System.String ToString()
+FSharp.Compiler.Syntax.SynValSig: Boolean IsSynValSig
+FSharp.Compiler.Syntax.SynValSig: Boolean get_IsSynValSig()
 FSharp.Compiler.Syntax.SynValSig: Boolean get_isInline()
 FSharp.Compiler.Syntax.SynValSig: Boolean get_isMutable()
 FSharp.Compiler.Syntax.SynValSig: Boolean isInline
@@ -9347,7 +9496,9 @@ FSharp.Compiler.Syntax.SynValSig: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Co
 FSharp.Compiler.Syntax.SynValSig: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr] get_synExpr()
 FSharp.Compiler.Syntax.SynValSig: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr] synExpr
 FSharp.Compiler.Syntax.SynValSig: System.String ToString()
+FSharp.Compiler.Syntax.SynValTyparDecls: Boolean IsSynValTyparDecls
 FSharp.Compiler.Syntax.SynValTyparDecls: Boolean canInfer
+FSharp.Compiler.Syntax.SynValTyparDecls: Boolean get_IsSynValTyparDecls()
 FSharp.Compiler.Syntax.SynValTyparDecls: Boolean get_canInfer()
 FSharp.Compiler.Syntax.SynValTyparDecls: FSharp.Compiler.Syntax.SynValTyparDecls NewSynValTyparDecls(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynTyparDecls], Boolean)
 FSharp.Compiler.Syntax.SynValTyparDecls: Int32 Tag
diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl
index 9c8364afe22..15b58c9aea1 100644
--- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl
+++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl
@@ -296,10 +296,30 @@ FSharp.Compiler.AbstractIL.IL+ILAttribute: Int32 get_Tag()
 FSharp.Compiler.AbstractIL.IL+ILAttribute: System.String ToString()
 FSharp.Compiler.AbstractIL.IL+ILAttributes: ILAttribute[] AsArray()
 FSharp.Compiler.AbstractIL.IL+ILAttributes: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILAttribute] AsList()
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Given: ILAttributes Item
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Given: ILAttributes get_Item()
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Reader: Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,FSharp.Compiler.AbstractIL.IL+ILAttribute[]] Item
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Reader: Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,FSharp.Compiler.AbstractIL.IL+ILAttribute[]] get_Item()
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Tags: Int32 Given
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Tags: Int32 Reader
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: Boolean IsGiven
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: Boolean IsReader
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: Boolean get_IsGiven()
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: Boolean get_IsReader()
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Given
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Reader
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: FSharp.Compiler.AbstractIL.IL+ILAttributesStored+Tags
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: ILAttributes GetCustomAttrs(Int32)
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: ILAttributesStored NewGiven(ILAttributes)
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: ILAttributesStored NewReader(Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,FSharp.Compiler.AbstractIL.IL+ILAttribute[]])
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: Int32 Tag
+FSharp.Compiler.AbstractIL.IL+ILAttributesStored: Int32 get_Tag()
 FSharp.Compiler.AbstractIL.IL+ILAttributesStored: System.String ToString()
 FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(ILCallingConv)
 FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(System.Object)
 FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean IsCallconv
+FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean get_IsCallconv()
 FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILArgConvention Item2
 FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILArgConvention get_Item2()
 FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILCallingConv Instance
@@ -390,10 +410,14 @@ FSharp.Compiler.AbstractIL.IL+ILEventDef: Boolean get_IsRTSpecialName()
 FSharp.Compiler.AbstractIL.IL+ILEventDef: Boolean get_IsSpecialName()
 FSharp.Compiler.AbstractIL.IL+ILEventDef: ILAttributes CustomAttrs
 FSharp.Compiler.AbstractIL.IL+ILEventDef: ILAttributes get_CustomAttrs()
+FSharp.Compiler.AbstractIL.IL+ILEventDef: ILAttributesStored CustomAttrsStored
+FSharp.Compiler.AbstractIL.IL+ILEventDef: ILAttributesStored get_CustomAttrsStored()
 FSharp.Compiler.AbstractIL.IL+ILEventDef: ILMethodRef AddMethod
 FSharp.Compiler.AbstractIL.IL+ILEventDef: ILMethodRef RemoveMethod
 FSharp.Compiler.AbstractIL.IL+ILEventDef: ILMethodRef get_AddMethod()
 FSharp.Compiler.AbstractIL.IL+ILEventDef: ILMethodRef get_RemoveMethod()
+FSharp.Compiler.AbstractIL.IL+ILEventDef: Int32 MetadataIndex
+FSharp.Compiler.AbstractIL.IL+ILEventDef: Int32 get_MetadataIndex()
 FSharp.Compiler.AbstractIL.IL+ILEventDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILMethodRef] OtherMethods
 FSharp.Compiler.AbstractIL.IL+ILEventDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILMethodRef] get_OtherMethods()
 FSharp.Compiler.AbstractIL.IL+ILEventDef: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILMethodRef] FireMethod
@@ -445,10 +469,14 @@ FSharp.Compiler.AbstractIL.IL+ILFieldDef: Boolean get_IsStatic()
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: Boolean get_NotSerialized()
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILAttributes CustomAttrs
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILAttributes get_CustomAttrs()
+FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILAttributesStored CustomAttrsStored
+FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILAttributesStored get_CustomAttrsStored()
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILMemberAccess Access
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILMemberAccess get_Access()
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILType FieldType
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: ILType get_FieldType()
+FSharp.Compiler.AbstractIL.IL+ILFieldDef: Int32 MetadataIndex
+FSharp.Compiler.AbstractIL.IL+ILFieldDef: Int32 get_MetadataIndex()
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILFieldInit] LiteralValue
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILFieldInit] get_LiteralValue()
 FSharp.Compiler.AbstractIL.IL+ILFieldDef: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILNativeType] Marshal
@@ -762,6 +790,8 @@ FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean get_IsVirtual()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: Boolean get_IsZeroInit()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILAttributes CustomAttrs
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILAttributes get_CustomAttrs()
+FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILAttributesStored CustomAttrsStored
+FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILAttributesStored get_CustomAttrsStored()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILCallingConv CallingConv
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILCallingConv get_CallingConv()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILCallingSignature GetCallingSignature()
@@ -774,7 +804,9 @@ FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILReturn get_Return()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILSecurityDecls SecurityDecls
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILSecurityDecls get_SecurityDecls()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: Int32 MaxStack
+FSharp.Compiler.AbstractIL.IL+ILMethodDef: Int32 MetadataIndex
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: Int32 get_MaxStack()
+FSharp.Compiler.AbstractIL.IL+ILMethodDef: Int32 get_MetadataIndex()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: MethodBody Body
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: MethodBody get_Body()
 FSharp.Compiler.AbstractIL.IL+ILMethodDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef] GenericParams
@@ -1230,10 +1262,14 @@ FSharp.Compiler.AbstractIL.IL+ILPropertyDef: Boolean get_IsRTSpecialName()
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: Boolean get_IsSpecialName()
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILAttributes CustomAttrs
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILAttributes get_CustomAttrs()
+FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILAttributesStored CustomAttrsStored
+FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILAttributesStored get_CustomAttrsStored()
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILThisConvention CallingConv
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILThisConvention get_CallingConv()
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILType PropertyType
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: ILType get_PropertyType()
+FSharp.Compiler.AbstractIL.IL+ILPropertyDef: Int32 MetadataIndex
+FSharp.Compiler.AbstractIL.IL+ILPropertyDef: Int32 get_MetadataIndex()
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType] Args
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType] get_Args()
 FSharp.Compiler.AbstractIL.IL+ILPropertyDef: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILFieldInit] Init
@@ -1490,6 +1526,8 @@ FSharp.Compiler.AbstractIL.IL+ILTypeDef: Boolean get_IsStruct()
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: Boolean get_IsStructOrEnum()
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILAttributes CustomAttrs
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILAttributes get_CustomAttrs()
+FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILAttributesStored CustomAttrsStored
+FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILAttributesStored get_CustomAttrsStored()
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILDefaultPInvokeEncoding Encoding
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILDefaultPInvokeEncoding get_Encoding()
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILEventDefs Events
@@ -1511,6 +1549,8 @@ FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDefLayout Layout
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDefLayout get_Layout()
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDefs NestedTypes
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDefs get_NestedTypes()
+FSharp.Compiler.AbstractIL.IL+ILTypeDef: Int32 MetadataIndex
+FSharp.Compiler.AbstractIL.IL+ILTypeDef: Int32 get_MetadataIndex()
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef] GenericParams
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef] get_GenericParams()
 FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType] Implements
@@ -4231,6 +4271,8 @@ FSharp.Compiler.EditorServices.ToolTipElementData: Void .ctor(Microsoft.FSharp.C
 FSharp.Compiler.EditorServices.ToolTipText: Boolean Equals(FSharp.Compiler.EditorServices.ToolTipText)
 FSharp.Compiler.EditorServices.ToolTipText: Boolean Equals(System.Object)
 FSharp.Compiler.EditorServices.ToolTipText: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.EditorServices.ToolTipText: Boolean IsToolTipText
+FSharp.Compiler.EditorServices.ToolTipText: Boolean get_IsToolTipText()
 FSharp.Compiler.EditorServices.ToolTipText: FSharp.Compiler.EditorServices.ToolTipText NewToolTipText(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.EditorServices.ToolTipElement])
 FSharp.Compiler.EditorServices.ToolTipText: Int32 GetHashCode()
 FSharp.Compiler.EditorServices.ToolTipText: Int32 GetHashCode(System.Collections.IEqualityComparer)
@@ -4274,6 +4316,8 @@ FSharp.Compiler.EditorServices.XmlDocParser: Microsoft.FSharp.Collections.FSharp
 FSharp.Compiler.EditorServices.XmlDocable: Boolean Equals(FSharp.Compiler.EditorServices.XmlDocable)
 FSharp.Compiler.EditorServices.XmlDocable: Boolean Equals(System.Object)
 FSharp.Compiler.EditorServices.XmlDocable: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.EditorServices.XmlDocable: Boolean IsXmlDocable
+FSharp.Compiler.EditorServices.XmlDocable: Boolean get_IsXmlDocable()
 FSharp.Compiler.EditorServices.XmlDocable: FSharp.Compiler.EditorServices.XmlDocable NewXmlDocable(Int32, Int32, Microsoft.FSharp.Collections.FSharpList`1[System.String])
 FSharp.Compiler.EditorServices.XmlDocable: Int32 CompareTo(FSharp.Compiler.EditorServices.XmlDocable)
 FSharp.Compiler.EditorServices.XmlDocable: Int32 CompareTo(System.Object)
@@ -5298,21 +5342,25 @@ FSharp.Compiler.Symbols.FSharpSymbolPatterns: Microsoft.FSharp.Core.FSharpOption
 FSharp.Compiler.Symbols.FSharpSymbolPatterns: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Symbols.FSharpField,FSharp.Compiler.Symbols.FSharpType]] |Field|_|(FSharp.Compiler.Symbols.FSharpSymbol)
 FSharp.Compiler.Symbols.FSharpSymbolPatterns: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.Symbols.FSharpEntity,FSharp.Compiler.Symbols.FSharpEntity,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Symbols.FSharpType]]] |FSharpEntity|_|(FSharp.Compiler.Symbols.FSharpSymbol)
 FSharp.Compiler.Symbols.FSharpType: Boolean Equals(System.Object)
+FSharp.Compiler.Symbols.FSharpType: Boolean HasNullAnnotation
 FSharp.Compiler.Symbols.FSharpType: Boolean HasTypeDefinition
 FSharp.Compiler.Symbols.FSharpType: Boolean IsAbbreviation
 FSharp.Compiler.Symbols.FSharpType: Boolean IsAnonRecordType
 FSharp.Compiler.Symbols.FSharpType: Boolean IsFunctionType
 FSharp.Compiler.Symbols.FSharpType: Boolean IsGenericParameter
 FSharp.Compiler.Symbols.FSharpType: Boolean IsMeasureType
+FSharp.Compiler.Symbols.FSharpType: Boolean IsNullAmbivalent
 FSharp.Compiler.Symbols.FSharpType: Boolean IsStructTupleType
 FSharp.Compiler.Symbols.FSharpType: Boolean IsTupleType
 FSharp.Compiler.Symbols.FSharpType: Boolean IsUnresolved
+FSharp.Compiler.Symbols.FSharpType: Boolean get_HasNullAnnotation()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_HasTypeDefinition()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsAbbreviation()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsAnonRecordType()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsFunctionType()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsGenericParameter()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsMeasureType()
+FSharp.Compiler.Symbols.FSharpType: Boolean get_IsNullAmbivalent()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsStructTupleType()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsTupleType()
 FSharp.Compiler.Symbols.FSharpType: Boolean get_IsUnresolved()
@@ -5508,6 +5556,8 @@ FSharp.Compiler.Syntax.DebugPointAtInOrTo: System.String ToString()
 FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean Equals(FSharp.Compiler.Syntax.DebugPointAtLeafExpr)
 FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean Equals(System.Object)
 FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean IsYes
+FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean get_IsYes()
 FSharp.Compiler.Syntax.DebugPointAtLeafExpr: FSharp.Compiler.Syntax.DebugPointAtLeafExpr NewYes(FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.DebugPointAtLeafExpr: FSharp.Compiler.Text.Range Item
 FSharp.Compiler.Syntax.DebugPointAtLeafExpr: FSharp.Compiler.Text.Range get_Item()
@@ -5642,6 +5692,8 @@ FSharp.Compiler.Syntax.Ident: System.String ToString()
 FSharp.Compiler.Syntax.Ident: System.String get_idText()
 FSharp.Compiler.Syntax.Ident: System.String idText
 FSharp.Compiler.Syntax.Ident: Void .ctor(System.String, FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.ParsedHashDirective: Boolean IsParsedHashDirective
+FSharp.Compiler.Syntax.ParsedHashDirective: Boolean get_IsParsedHashDirective()
 FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Syntax.ParsedHashDirective NewParsedHashDirective(System.String, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirectiveArgument], FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Text.Range get_range()
 FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Text.Range range
@@ -5680,6 +5732,8 @@ FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: FSharp.Compiler.Text.Range g
 FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: Int32 Tag
 FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: Int32 get_Tag()
 FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: System.String ToString()
+FSharp.Compiler.Syntax.ParsedImplFile: Boolean IsParsedImplFile
+FSharp.Compiler.Syntax.ParsedImplFile: Boolean get_IsParsedImplFile()
 FSharp.Compiler.Syntax.ParsedImplFile: FSharp.Compiler.Syntax.ParsedImplFile NewParsedImplFile(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirective], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedImplFileFragment])
 FSharp.Compiler.Syntax.ParsedImplFile: Int32 Tag
 FSharp.Compiler.Syntax.ParsedImplFile: Int32 get_Tag()
@@ -5731,9 +5785,11 @@ FSharp.Compiler.Syntax.ParsedImplFileFragment: Int32 get_Tag()
 FSharp.Compiler.Syntax.ParsedImplFileFragment: System.String ToString()
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsExe
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsLastCompiland
+FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsParsedImplFileInput
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsScript
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsExe()
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsLastCompiland()
+FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsParsedImplFileInput()
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsScript()
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_isScript()
 FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean isScript
@@ -5797,6 +5853,8 @@ FSharp.Compiler.Syntax.ParsedInput: Microsoft.FSharp.Collections.FSharpSet`1[Sys
 FSharp.Compiler.Syntax.ParsedInput: System.String FileName
 FSharp.Compiler.Syntax.ParsedInput: System.String ToString()
 FSharp.Compiler.Syntax.ParsedInput: System.String get_FileName()
+FSharp.Compiler.Syntax.ParsedScriptInteraction: Boolean IsDefinitions
+FSharp.Compiler.Syntax.ParsedScriptInteraction: Boolean get_IsDefinitions()
 FSharp.Compiler.Syntax.ParsedScriptInteraction: FSharp.Compiler.Syntax.ParsedScriptInteraction NewDefinitions(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl], FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.ParsedScriptInteraction: FSharp.Compiler.Text.Range get_range()
 FSharp.Compiler.Syntax.ParsedScriptInteraction: FSharp.Compiler.Text.Range range
@@ -5805,6 +5863,8 @@ FSharp.Compiler.Syntax.ParsedScriptInteraction: Int32 get_Tag()
 FSharp.Compiler.Syntax.ParsedScriptInteraction: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl] defns
 FSharp.Compiler.Syntax.ParsedScriptInteraction: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl] get_defns()
 FSharp.Compiler.Syntax.ParsedScriptInteraction: System.String ToString()
+FSharp.Compiler.Syntax.ParsedSigFile: Boolean IsParsedSigFile
+FSharp.Compiler.Syntax.ParsedSigFile: Boolean get_IsParsedSigFile()
 FSharp.Compiler.Syntax.ParsedSigFile: FSharp.Compiler.Syntax.ParsedSigFile NewParsedSigFile(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirective], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedSigFileFragment])
 FSharp.Compiler.Syntax.ParsedSigFile: Int32 Tag
 FSharp.Compiler.Syntax.ParsedSigFile: Int32 get_Tag()
@@ -5854,6 +5914,8 @@ FSharp.Compiler.Syntax.ParsedSigFileFragment: FSharp.Compiler.Syntax.ParsedSigFi
 FSharp.Compiler.Syntax.ParsedSigFileFragment: Int32 Tag
 FSharp.Compiler.Syntax.ParsedSigFileFragment: Int32 get_Tag()
 FSharp.Compiler.Syntax.ParsedSigFileFragment: System.String ToString()
+FSharp.Compiler.Syntax.ParsedSigFileInput: Boolean IsParsedSigFileInput
+FSharp.Compiler.Syntax.ParsedSigFileInput: Boolean get_IsParsedSigFileInput()
 FSharp.Compiler.Syntax.ParsedSigFileInput: FSharp.Compiler.Syntax.ParsedSigFileInput NewParsedSigFileInput(System.String, FSharp.Compiler.Syntax.QualifiedNameOfFile, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ScopedPragma], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirective], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleOrNamespaceSig], FSharp.Compiler.SyntaxTrivia.ParsedSigFileInputTrivia, Microsoft.FSharp.Collections.FSharpSet`1[System.String])
 FSharp.Compiler.Syntax.ParsedSigFileInput: FSharp.Compiler.Syntax.QualifiedNameOfFile QualifiedName
 FSharp.Compiler.Syntax.ParsedSigFileInput: FSharp.Compiler.Syntax.QualifiedNameOfFile get_QualifiedName()
@@ -5926,6 +5988,8 @@ FSharp.Compiler.Syntax.PrettyNaming: System.String FormatAndOtherOverloadsString
 FSharp.Compiler.Syntax.PrettyNaming: System.String FsiDynamicModulePrefix
 FSharp.Compiler.Syntax.PrettyNaming: System.String NormalizeIdentifierBackticks(System.String)
 FSharp.Compiler.Syntax.PrettyNaming: System.String get_FsiDynamicModulePrefix()
+FSharp.Compiler.Syntax.QualifiedNameOfFile: Boolean IsQualifiedNameOfFile
+FSharp.Compiler.Syntax.QualifiedNameOfFile: Boolean get_IsQualifiedNameOfFile()
 FSharp.Compiler.Syntax.QualifiedNameOfFile: FSharp.Compiler.Syntax.Ident Id
 FSharp.Compiler.Syntax.QualifiedNameOfFile: FSharp.Compiler.Syntax.Ident Item
 FSharp.Compiler.Syntax.QualifiedNameOfFile: FSharp.Compiler.Syntax.Ident get_Id()
@@ -5941,6 +6005,8 @@ FSharp.Compiler.Syntax.QualifiedNameOfFile: System.String get_Text()
 FSharp.Compiler.Syntax.ScopedPragma: Boolean Equals(FSharp.Compiler.Syntax.ScopedPragma)
 FSharp.Compiler.Syntax.ScopedPragma: Boolean Equals(System.Object)
 FSharp.Compiler.Syntax.ScopedPragma: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.Syntax.ScopedPragma: Boolean IsWarningOff
+FSharp.Compiler.Syntax.ScopedPragma: Boolean get_IsWarningOff()
 FSharp.Compiler.Syntax.ScopedPragma: FSharp.Compiler.Syntax.ScopedPragma NewWarningOff(FSharp.Compiler.Text.Range, Int32)
 FSharp.Compiler.Syntax.ScopedPragma: FSharp.Compiler.Text.Range get_range()
 FSharp.Compiler.Syntax.ScopedPragma: FSharp.Compiler.Text.Range range
@@ -5954,7 +6020,9 @@ FSharp.Compiler.Syntax.ScopedPragma: System.String ToString()
 FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(FSharp.Compiler.Syntax.SeqExprOnly)
 FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(System.Object)
 FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.Syntax.SeqExprOnly: Boolean IsSeqExprOnly
 FSharp.Compiler.Syntax.SeqExprOnly: Boolean Item
+FSharp.Compiler.Syntax.SeqExprOnly: Boolean get_IsSeqExprOnly()
 FSharp.Compiler.Syntax.SeqExprOnly: Boolean get_Item()
 FSharp.Compiler.Syntax.SeqExprOnly: FSharp.Compiler.Syntax.SeqExprOnly NewSeqExprOnly(Boolean)
 FSharp.Compiler.Syntax.SeqExprOnly: Int32 CompareTo(FSharp.Compiler.Syntax.SeqExprOnly)
@@ -5997,6 +6065,8 @@ FSharp.Compiler.Syntax.SynAccess: Int32 GetHashCode(System.Collections.IEquality
 FSharp.Compiler.Syntax.SynAccess: Int32 Tag
 FSharp.Compiler.Syntax.SynAccess: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynAccess: System.String ToString()
+FSharp.Compiler.Syntax.SynArgInfo: Boolean IsSynArgInfo
+FSharp.Compiler.Syntax.SynArgInfo: Boolean get_IsSynArgInfo()
 FSharp.Compiler.Syntax.SynArgInfo: Boolean get_optional()
 FSharp.Compiler.Syntax.SynArgInfo: Boolean optional
 FSharp.Compiler.Syntax.SynArgInfo: FSharp.Compiler.Syntax.SynArgInfo NewSynArgInfo(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident])
@@ -6053,6 +6123,8 @@ FSharp.Compiler.Syntax.SynAttributeList: Microsoft.FSharp.Collections.FSharpList
 FSharp.Compiler.Syntax.SynAttributeList: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttribute] get_Attributes()
 FSharp.Compiler.Syntax.SynAttributeList: System.String ToString()
 FSharp.Compiler.Syntax.SynAttributeList: Void .ctor(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttribute], FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynBinding: Boolean IsSynBinding
+FSharp.Compiler.Syntax.SynBinding: Boolean get_IsSynBinding()
 FSharp.Compiler.Syntax.SynBinding: Boolean get_isInline()
 FSharp.Compiler.Syntax.SynBinding: Boolean get_isMutable()
 FSharp.Compiler.Syntax.SynBinding: Boolean isInline
@@ -6116,6 +6188,8 @@ FSharp.Compiler.Syntax.SynBindingKind: Int32 GetHashCode(System.Collections.IEqu
 FSharp.Compiler.Syntax.SynBindingKind: Int32 Tag
 FSharp.Compiler.Syntax.SynBindingKind: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynBindingKind: System.String ToString()
+FSharp.Compiler.Syntax.SynBindingReturnInfo: Boolean IsSynBindingReturnInfo
+FSharp.Compiler.Syntax.SynBindingReturnInfo: Boolean get_IsSynBindingReturnInfo()
 FSharp.Compiler.Syntax.SynBindingReturnInfo: FSharp.Compiler.Syntax.SynBindingReturnInfo NewSynBindingReturnInfo(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.SyntaxTrivia.SynBindingReturnInfoTrivia)
 FSharp.Compiler.Syntax.SynBindingReturnInfo: FSharp.Compiler.Syntax.SynType get_typeName()
 FSharp.Compiler.Syntax.SynBindingReturnInfo: FSharp.Compiler.Syntax.SynType typeName
@@ -6150,6 +6224,8 @@ FSharp.Compiler.Syntax.SynByteStringKind: Int32 GetHashCode(System.Collections.I
 FSharp.Compiler.Syntax.SynByteStringKind: Int32 Tag
 FSharp.Compiler.Syntax.SynByteStringKind: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynByteStringKind: System.String ToString()
+FSharp.Compiler.Syntax.SynComponentInfo: Boolean IsSynComponentInfo
+FSharp.Compiler.Syntax.SynComponentInfo: Boolean get_IsSynComponentInfo()
 FSharp.Compiler.Syntax.SynComponentInfo: Boolean get_preferPostfix()
 FSharp.Compiler.Syntax.SynComponentInfo: Boolean preferPostfix
 FSharp.Compiler.Syntax.SynComponentInfo: FSharp.Compiler.Syntax.SynComponentInfo NewSynComponentInfo(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynTyparDecls], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynTypeConstraint], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Xml.PreXmlDoc, Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range)
@@ -6349,6 +6425,8 @@ FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Text.Range Range(FSharp.Compile
 FSharp.Compiler.Syntax.SynConst: Int32 Tag
 FSharp.Compiler.Syntax.SynConst: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynConst: System.String ToString()
+FSharp.Compiler.Syntax.SynEnumCase: Boolean IsSynEnumCase
+FSharp.Compiler.Syntax.SynEnumCase: Boolean get_IsSynEnumCase()
 FSharp.Compiler.Syntax.SynEnumCase: FSharp.Compiler.Syntax.SynEnumCase NewSynEnumCase(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynIdent, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynEnumCaseTrivia)
 FSharp.Compiler.Syntax.SynEnumCase: FSharp.Compiler.Syntax.SynExpr get_valueExpr()
 FSharp.Compiler.Syntax.SynEnumCase: FSharp.Compiler.Syntax.SynExpr valueExpr
@@ -6367,6 +6445,8 @@ 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.SynExceptionDefn: Boolean IsSynExceptionDefn
+FSharp.Compiler.Syntax.SynExceptionDefn: Boolean get_IsSynExceptionDefn()
 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
 FSharp.Compiler.Syntax.SynExceptionDefn: FSharp.Compiler.Syntax.SynExceptionDefnRepr get_exnRepr()
@@ -6381,6 +6461,8 @@ FSharp.Compiler.Syntax.SynExceptionDefn: Microsoft.FSharp.Collections.FSharpList
 FSharp.Compiler.Syntax.SynExceptionDefn: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_withKeyword()
 FSharp.Compiler.Syntax.SynExceptionDefn: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] withKeyword
 FSharp.Compiler.Syntax.SynExceptionDefn: System.String ToString()
+FSharp.Compiler.Syntax.SynExceptionDefnRepr: Boolean IsSynExceptionDefnRepr
+FSharp.Compiler.Syntax.SynExceptionDefnRepr: Boolean get_IsSynExceptionDefnRepr()
 FSharp.Compiler.Syntax.SynExceptionDefnRepr: FSharp.Compiler.Syntax.SynExceptionDefnRepr NewSynExceptionDefnRepr(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynUnionCase, Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident]], FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynExceptionDefnRepr: FSharp.Compiler.Syntax.SynUnionCase caseName
 FSharp.Compiler.Syntax.SynExceptionDefnRepr: FSharp.Compiler.Syntax.SynUnionCase get_caseName()
@@ -6399,6 +6481,8 @@ FSharp.Compiler.Syntax.SynExceptionDefnRepr: Microsoft.FSharp.Core.FSharpOption`
 FSharp.Compiler.Syntax.SynExceptionDefnRepr: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident]] get_longId()
 FSharp.Compiler.Syntax.SynExceptionDefnRepr: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident]] longId
 FSharp.Compiler.Syntax.SynExceptionDefnRepr: System.String ToString()
+FSharp.Compiler.Syntax.SynExceptionSig: Boolean IsSynExceptionSig
+FSharp.Compiler.Syntax.SynExceptionSig: Boolean get_IsSynExceptionSig()
 FSharp.Compiler.Syntax.SynExceptionSig: FSharp.Compiler.Syntax.SynExceptionDefnRepr exnRepr
 FSharp.Compiler.Syntax.SynExceptionSig: FSharp.Compiler.Syntax.SynExceptionDefnRepr get_exnRepr()
 FSharp.Compiler.Syntax.SynExceptionSig: FSharp.Compiler.Syntax.SynExceptionSig NewSynExceptionSig(FSharp.Compiler.Syntax.SynExceptionDefnRepr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberSig], FSharp.Compiler.Text.Range)
@@ -7333,6 +7417,8 @@ FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Text.Range get_RangeWithoutAnyEx
 FSharp.Compiler.Syntax.SynExpr: Int32 Tag
 FSharp.Compiler.Syntax.SynExpr: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynExpr: System.String ToString()
+FSharp.Compiler.Syntax.SynExprAndBang: Boolean IsSynExprAndBang
+FSharp.Compiler.Syntax.SynExprAndBang: Boolean get_IsSynExprAndBang()
 FSharp.Compiler.Syntax.SynExprAndBang: Boolean get_isFromSource()
 FSharp.Compiler.Syntax.SynExprAndBang: Boolean get_isUse()
 FSharp.Compiler.Syntax.SynExprAndBang: Boolean isFromSource
@@ -7351,6 +7437,8 @@ FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Text.Range range
 FSharp.Compiler.Syntax.SynExprAndBang: Int32 Tag
 FSharp.Compiler.Syntax.SynExprAndBang: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynExprAndBang: System.String ToString()
+FSharp.Compiler.Syntax.SynExprRecordField: Boolean IsSynExprRecordField
+FSharp.Compiler.Syntax.SynExprRecordField: Boolean get_IsSynExprRecordField()
 FSharp.Compiler.Syntax.SynExprRecordField: FSharp.Compiler.Syntax.SynExprRecordField NewSynExprRecordField(System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr], Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]])
 FSharp.Compiler.Syntax.SynExprRecordField: Int32 Tag
 FSharp.Compiler.Syntax.SynExprRecordField: Int32 get_Tag()
@@ -7363,6 +7451,8 @@ FSharp.Compiler.Syntax.SynExprRecordField: Microsoft.FSharp.Core.FSharpOption`1[
 FSharp.Compiler.Syntax.SynExprRecordField: System.String ToString()
 FSharp.Compiler.Syntax.SynExprRecordField: System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean] fieldName
 FSharp.Compiler.Syntax.SynExprRecordField: System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean] get_fieldName()
+FSharp.Compiler.Syntax.SynField: Boolean IsSynField
+FSharp.Compiler.Syntax.SynField: Boolean get_IsSynField()
 FSharp.Compiler.Syntax.SynField: Boolean get_isMutable()
 FSharp.Compiler.Syntax.SynField: Boolean get_isStatic()
 FSharp.Compiler.Syntax.SynField: Boolean isMutable
@@ -7387,6 +7477,8 @@ FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Com
 FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] accessibility
 FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] get_accessibility()
 FSharp.Compiler.Syntax.SynField: System.String ToString()
+FSharp.Compiler.Syntax.SynIdent: Boolean IsSynIdent
+FSharp.Compiler.Syntax.SynIdent: Boolean get_IsSynIdent()
 FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.Ident get_ident()
 FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.Ident ident
 FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.SynIdent NewSynIdent(FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia])
@@ -7395,6 +7487,8 @@ FSharp.Compiler.Syntax.SynIdent: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia] get_trivia()
 FSharp.Compiler.Syntax.SynIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia] trivia
 FSharp.Compiler.Syntax.SynIdent: System.String ToString()
+FSharp.Compiler.Syntax.SynInterfaceImpl: Boolean IsSynInterfaceImpl
+FSharp.Compiler.Syntax.SynInterfaceImpl: Boolean get_IsSynInterfaceImpl()
 FSharp.Compiler.Syntax.SynInterfaceImpl: FSharp.Compiler.Syntax.SynInterfaceImpl NewSynInterfaceImpl(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynBinding], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn], FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynInterfaceImpl: FSharp.Compiler.Syntax.SynType get_interfaceTy()
 FSharp.Compiler.Syntax.SynInterfaceImpl: FSharp.Compiler.Syntax.SynType interfaceTy
@@ -7431,7 +7525,9 @@ FSharp.Compiler.Syntax.SynInterpolatedStringPart: FSharp.Compiler.Syntax.SynInte
 FSharp.Compiler.Syntax.SynInterpolatedStringPart: Int32 Tag
 FSharp.Compiler.Syntax.SynInterpolatedStringPart: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynInterpolatedStringPart: System.String ToString()
+FSharp.Compiler.Syntax.SynLongIdent: Boolean IsSynLongIdent
 FSharp.Compiler.Syntax.SynLongIdent: Boolean ThereIsAnExtraDotAtTheEnd
+FSharp.Compiler.Syntax.SynLongIdent: Boolean get_IsSynLongIdent()
 FSharp.Compiler.Syntax.SynLongIdent: Boolean get_ThereIsAnExtraDotAtTheEnd()
 FSharp.Compiler.Syntax.SynLongIdent: FSharp.Compiler.Syntax.SynLongIdent NewSynLongIdent(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia]])
 FSharp.Compiler.Syntax.SynLongIdent: FSharp.Compiler.Text.Range Range
@@ -7457,6 +7553,8 @@ FSharp.Compiler.Syntax.SynLongIdent: Microsoft.FSharp.Collections.FSharpList`1[M
 FSharp.Compiler.Syntax.SynLongIdent: System.String ToString()
 FSharp.Compiler.Syntax.SynLongIdentHelpers: FSharp.Compiler.Syntax.SynLongIdent LongIdentWithDots(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range])
 FSharp.Compiler.Syntax.SynLongIdentHelpers: System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident],Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range]] |LongIdentWithDots|(FSharp.Compiler.Syntax.SynLongIdent)
+FSharp.Compiler.Syntax.SynMatchClause: Boolean IsSynMatchClause
+FSharp.Compiler.Syntax.SynMatchClause: Boolean get_IsSynMatchClause()
 FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.DebugPointAtTarget debugPoint
 FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.DebugPointAtTarget get_debugPoint()
 FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.SynExpr get_resultExpr()
@@ -7954,6 +8052,8 @@ FSharp.Compiler.Syntax.SynModuleDecl: FSharp.Compiler.Text.Range get_Range()
 FSharp.Compiler.Syntax.SynModuleDecl: Int32 Tag
 FSharp.Compiler.Syntax.SynModuleDecl: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynModuleDecl: System.String ToString()
+FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean IsSynModuleOrNamespace
+FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean get_IsSynModuleOrNamespace()
 FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean get_isRecursive()
 FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean isRecursive
 FSharp.Compiler.Syntax.SynModuleOrNamespace: FSharp.Compiler.Syntax.SynModuleOrNamespace NewSynModuleOrNamespace(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], Boolean, FSharp.Compiler.Syntax.SynModuleOrNamespaceKind, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl], FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynModuleOrNamespaceTrivia)
@@ -8012,6 +8112,8 @@ FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: Int32 GetHashCode(System.Collec
 FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: Int32 Tag
 FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: System.String ToString()
+FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean IsSynModuleOrNamespaceSig
+FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean get_IsSynModuleOrNamespaceSig()
 FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean get_isRecursive()
 FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean isRecursive
 FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: FSharp.Compiler.Syntax.SynModuleOrNamespaceKind get_kind()
@@ -8412,6 +8514,8 @@ FSharp.Compiler.Syntax.SynRationalConst: FSharp.Compiler.Syntax.SynRationalConst
 FSharp.Compiler.Syntax.SynRationalConst: Int32 Tag
 FSharp.Compiler.Syntax.SynRationalConst: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynRationalConst: System.String ToString()
+FSharp.Compiler.Syntax.SynReturnInfo: Boolean IsSynReturnInfo
+FSharp.Compiler.Syntax.SynReturnInfo: Boolean get_IsSynReturnInfo()
 FSharp.Compiler.Syntax.SynReturnInfo: FSharp.Compiler.Syntax.SynReturnInfo NewSynReturnInfo(System.Tuple`2[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Syntax.SynArgInfo], FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynReturnInfo: FSharp.Compiler.Text.Range Range
 FSharp.Compiler.Syntax.SynReturnInfo: FSharp.Compiler.Text.Range get_Range()
@@ -8485,6 +8589,8 @@ FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: FSharp.Compiler.Syntax.Syn
 FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: Int32 Tag
 FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: System.String ToString()
+FSharp.Compiler.Syntax.SynSimplePats: Boolean IsSimplePats
+FSharp.Compiler.Syntax.SynSimplePats: Boolean get_IsSimplePats()
 FSharp.Compiler.Syntax.SynSimplePats: FSharp.Compiler.Syntax.SynSimplePats NewSimplePats(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynSimplePat], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range], FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynSimplePats: FSharp.Compiler.Text.Range Range
 FSharp.Compiler.Syntax.SynSimplePats: FSharp.Compiler.Text.Range get_Range()
@@ -8575,6 +8681,8 @@ FSharp.Compiler.Syntax.SynTupleTypeSegment: FSharp.Compiler.Text.Range get_Range
 FSharp.Compiler.Syntax.SynTupleTypeSegment: Int32 Tag
 FSharp.Compiler.Syntax.SynTupleTypeSegment: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynTupleTypeSegment: System.String ToString()
+FSharp.Compiler.Syntax.SynTypar: Boolean IsSynTypar
+FSharp.Compiler.Syntax.SynTypar: Boolean get_IsSynTypar()
 FSharp.Compiler.Syntax.SynTypar: Boolean get_isCompGen()
 FSharp.Compiler.Syntax.SynTypar: Boolean isCompGen
 FSharp.Compiler.Syntax.SynTypar: FSharp.Compiler.Syntax.Ident get_ident()
@@ -8587,6 +8695,8 @@ FSharp.Compiler.Syntax.SynTypar: FSharp.Compiler.Text.Range get_Range()
 FSharp.Compiler.Syntax.SynTypar: Int32 Tag
 FSharp.Compiler.Syntax.SynTypar: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynTypar: System.String ToString()
+FSharp.Compiler.Syntax.SynTyparDecl: Boolean IsSynTyparDecl
+FSharp.Compiler.Syntax.SynTyparDecl: Boolean get_IsSynTyparDecl()
 FSharp.Compiler.Syntax.SynTyparDecl: FSharp.Compiler.Syntax.SynTypar get_typar()
 FSharp.Compiler.Syntax.SynTyparDecl: FSharp.Compiler.Syntax.SynTypar typar
 FSharp.Compiler.Syntax.SynTyparDecl: FSharp.Compiler.Syntax.SynTyparDecl NewSynTyparDecl(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynTypar, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynType], FSharp.Compiler.SyntaxTrivia.SynTyparDeclTrivia)
@@ -8746,6 +8856,8 @@ FSharp.Compiler.Syntax.SynType+StaticConstantNamed: FSharp.Compiler.Syntax.SynTy
 FSharp.Compiler.Syntax.SynType+StaticConstantNamed: FSharp.Compiler.Syntax.SynType value
 FSharp.Compiler.Syntax.SynType+StaticConstantNamed: FSharp.Compiler.Text.Range get_range()
 FSharp.Compiler.Syntax.SynType+StaticConstantNamed: FSharp.Compiler.Text.Range range
+FSharp.Compiler.Syntax.SynType+StaticConstantNull: FSharp.Compiler.Text.Range get_range()
+FSharp.Compiler.Syntax.SynType+StaticConstantNull: FSharp.Compiler.Text.Range range
 FSharp.Compiler.Syntax.SynType+Tags: Int32 Anon
 FSharp.Compiler.Syntax.SynType+Tags: Int32 AnonRecd
 FSharp.Compiler.Syntax.SynType+Tags: Int32 App
@@ -8763,9 +8875,11 @@ FSharp.Compiler.Syntax.SynType+Tags: Int32 SignatureParameter
 FSharp.Compiler.Syntax.SynType+Tags: Int32 StaticConstant
 FSharp.Compiler.Syntax.SynType+Tags: Int32 StaticConstantExpr
 FSharp.Compiler.Syntax.SynType+Tags: Int32 StaticConstantNamed
+FSharp.Compiler.Syntax.SynType+Tags: Int32 StaticConstantNull
 FSharp.Compiler.Syntax.SynType+Tags: Int32 Tuple
 FSharp.Compiler.Syntax.SynType+Tags: Int32 Var
 FSharp.Compiler.Syntax.SynType+Tags: Int32 WithGlobalConstraints
+FSharp.Compiler.Syntax.SynType+Tags: Int32 WithNull
 FSharp.Compiler.Syntax.SynType+Tuple: Boolean get_isStruct()
 FSharp.Compiler.Syntax.SynType+Tuple: Boolean isStruct
 FSharp.Compiler.Syntax.SynType+Tuple: FSharp.Compiler.Text.Range get_range()
@@ -8782,6 +8896,12 @@ FSharp.Compiler.Syntax.SynType+WithGlobalConstraints: FSharp.Compiler.Text.Range
 FSharp.Compiler.Syntax.SynType+WithGlobalConstraints: FSharp.Compiler.Text.Range range
 FSharp.Compiler.Syntax.SynType+WithGlobalConstraints: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynTypeConstraint] constraints
 FSharp.Compiler.Syntax.SynType+WithGlobalConstraints: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynTypeConstraint] get_constraints()
+FSharp.Compiler.Syntax.SynType+WithNull: Boolean ambivalent
+FSharp.Compiler.Syntax.SynType+WithNull: Boolean get_ambivalent()
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Syntax.SynType get_innerType()
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Syntax.SynType innerType
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Text.Range get_range()
+FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Text.Range range
 FSharp.Compiler.Syntax.SynType: Boolean IsAnon
 FSharp.Compiler.Syntax.SynType: Boolean IsAnonRecd
 FSharp.Compiler.Syntax.SynType: Boolean IsApp
@@ -8799,9 +8919,11 @@ FSharp.Compiler.Syntax.SynType: Boolean IsSignatureParameter
 FSharp.Compiler.Syntax.SynType: Boolean IsStaticConstant
 FSharp.Compiler.Syntax.SynType: Boolean IsStaticConstantExpr
 FSharp.Compiler.Syntax.SynType: Boolean IsStaticConstantNamed
+FSharp.Compiler.Syntax.SynType: Boolean IsStaticConstantNull
 FSharp.Compiler.Syntax.SynType: Boolean IsTuple
 FSharp.Compiler.Syntax.SynType: Boolean IsVar
 FSharp.Compiler.Syntax.SynType: Boolean IsWithGlobalConstraints
+FSharp.Compiler.Syntax.SynType: Boolean IsWithNull
 FSharp.Compiler.Syntax.SynType: Boolean get_IsAnon()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsAnonRecd()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsApp()
@@ -8819,9 +8941,11 @@ FSharp.Compiler.Syntax.SynType: Boolean get_IsSignatureParameter()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsStaticConstant()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsStaticConstantExpr()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsStaticConstantNamed()
+FSharp.Compiler.Syntax.SynType: Boolean get_IsStaticConstantNull()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsTuple()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsVar()
 FSharp.Compiler.Syntax.SynType: Boolean get_IsWithGlobalConstraints()
+FSharp.Compiler.Syntax.SynType: Boolean get_IsWithNull()
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewAnon(FSharp.Compiler.Text.Range)
 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)
@@ -8839,9 +8963,11 @@ FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewSignatureParam
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewStaticConstant(FSharp.Compiler.Syntax.SynConst, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewStaticConstantExpr(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewStaticConstantNamed(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewStaticConstantNull(FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewTuple(Boolean, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynTupleTypeSegment], FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewVar(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewWithGlobalConstraints(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynTypeConstraint], FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewWithNull(FSharp.Compiler.Syntax.SynType, Boolean, FSharp.Compiler.Text.Range)
 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
@@ -8859,10 +8985,12 @@ FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+SignatureParamete
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+StaticConstant
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+StaticConstantExpr
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+StaticConstantNamed
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+StaticConstantNull
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+Tags
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+Tuple
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+Var
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+WithGlobalConstraints
+FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+WithNull
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Text.Range Range
 FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Text.Range get_Range()
 FSharp.Compiler.Syntax.SynType: Int32 Tag
@@ -8877,6 +9005,7 @@ FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparIsEquatable
 FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparIsReferenceType
 FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparIsUnmanaged
 FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparIsValueType
+FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparNotSupportsNull
 FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparSubtypeOfType
 FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparSupportsMember
 FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparSupportsNull
@@ -8922,6 +9051,10 @@ FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparIsValueType: FSharp.Compiler.
 FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparIsValueType: FSharp.Compiler.Syntax.SynTypar typar
 FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparIsValueType: FSharp.Compiler.Text.Range get_range()
 FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparIsValueType: FSharp.Compiler.Text.Range range
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Syntax.SynTypar genericName
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Syntax.SynTypar get_genericName()
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Text.Range get_range()
+FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Text.Range range
 FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparSubtypeOfType: FSharp.Compiler.Syntax.SynTypar get_typar()
 FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparSubtypeOfType: FSharp.Compiler.Syntax.SynTypar typar
 FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparSubtypeOfType: FSharp.Compiler.Syntax.SynType get_typeName()
@@ -8947,6 +9080,7 @@ FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparIsEquatable
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparIsReferenceType
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparIsUnmanaged
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparIsValueType
+FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparNotSupportsNull
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparSubtypeOfType
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparSupportsMember
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparSupportsNull
@@ -8959,6 +9093,7 @@ FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparIsEquatable()
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparIsReferenceType()
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparIsUnmanaged()
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparIsValueType()
+FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparNotSupportsNull()
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparSubtypeOfType()
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparSupportsMember()
 FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparSupportsNull()
@@ -8971,6 +9106,7 @@ FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstrai
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparIsReferenceType(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparIsUnmanaged(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparIsValueType(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparNotSupportsNull(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparSubtypeOfType(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparSupportsMember(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynMemberSig, FSharp.Compiler.Text.Range)
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparSupportsNull(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
@@ -8984,6 +9120,7 @@ FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstrai
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparIsReferenceType
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparIsUnmanaged
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparIsValueType
+FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparSubtypeOfType
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparSupportsMember
 FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparSupportsNull
@@ -8992,6 +9129,8 @@ FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Text.Range get_Range()
 FSharp.Compiler.Syntax.SynTypeConstraint: Int32 Tag
 FSharp.Compiler.Syntax.SynTypeConstraint: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynTypeConstraint: System.String ToString()
+FSharp.Compiler.Syntax.SynTypeDefn: Boolean IsSynTypeDefn
+FSharp.Compiler.Syntax.SynTypeDefn: Boolean get_IsSynTypeDefn()
 FSharp.Compiler.Syntax.SynTypeDefn: FSharp.Compiler.Syntax.SynComponentInfo get_typeInfo()
 FSharp.Compiler.Syntax.SynTypeDefn: FSharp.Compiler.Syntax.SynComponentInfo typeInfo
 FSharp.Compiler.Syntax.SynTypeDefn: FSharp.Compiler.Syntax.SynTypeDefn NewSynTypeDefn(FSharp.Compiler.Syntax.SynComponentInfo, FSharp.Compiler.Syntax.SynTypeDefnRepr, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberDefn], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynTypeDefnTrivia)
@@ -9108,6 +9247,8 @@ FSharp.Compiler.Syntax.SynTypeDefnRepr: FSharp.Compiler.Text.Range get_Range()
 FSharp.Compiler.Syntax.SynTypeDefnRepr: Int32 Tag
 FSharp.Compiler.Syntax.SynTypeDefnRepr: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynTypeDefnRepr: System.String ToString()
+FSharp.Compiler.Syntax.SynTypeDefnSig: Boolean IsSynTypeDefnSig
+FSharp.Compiler.Syntax.SynTypeDefnSig: Boolean get_IsSynTypeDefnSig()
 FSharp.Compiler.Syntax.SynTypeDefnSig: FSharp.Compiler.Syntax.SynComponentInfo get_typeInfo()
 FSharp.Compiler.Syntax.SynTypeDefnSig: FSharp.Compiler.Syntax.SynComponentInfo typeInfo
 FSharp.Compiler.Syntax.SynTypeDefnSig: FSharp.Compiler.Syntax.SynTypeDefnSig NewSynTypeDefnSig(FSharp.Compiler.Syntax.SynComponentInfo, FSharp.Compiler.Syntax.SynTypeDefnSigRepr, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberSig], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynTypeDefnSigTrivia)
@@ -9249,6 +9390,8 @@ FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Text.Range get_Ran
 FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: Int32 Tag
 FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: System.String ToString()
+FSharp.Compiler.Syntax.SynUnionCase: Boolean IsSynUnionCase
+FSharp.Compiler.Syntax.SynUnionCase: Boolean get_IsSynUnionCase()
 FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynIdent get_ident()
 FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynIdent ident
 FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynUnionCase NewSynUnionCase(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynIdent, FSharp.Compiler.Syntax.SynUnionCaseKind, FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynUnionCaseTrivia)
@@ -9289,6 +9432,8 @@ FSharp.Compiler.Syntax.SynUnionCaseKind: FSharp.Compiler.Syntax.SynUnionCaseKind
 FSharp.Compiler.Syntax.SynUnionCaseKind: Int32 Tag
 FSharp.Compiler.Syntax.SynUnionCaseKind: Int32 get_Tag()
 FSharp.Compiler.Syntax.SynUnionCaseKind: System.String ToString()
+FSharp.Compiler.Syntax.SynValData: Boolean IsSynValData
+FSharp.Compiler.Syntax.SynValData: Boolean get_IsSynValData()
 FSharp.Compiler.Syntax.SynValData: FSharp.Compiler.Syntax.SynValData NewSynValData(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberFlags], FSharp.Compiler.Syntax.SynValInfo, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident])
 FSharp.Compiler.Syntax.SynValData: FSharp.Compiler.Syntax.SynValInfo SynValInfo
 FSharp.Compiler.Syntax.SynValData: FSharp.Compiler.Syntax.SynValInfo get_SynValInfo()
@@ -9301,6 +9446,8 @@ FSharp.Compiler.Syntax.SynValData: Microsoft.FSharp.Core.FSharpOption`1[FSharp.C
 FSharp.Compiler.Syntax.SynValData: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberFlags] get_memberFlags()
 FSharp.Compiler.Syntax.SynValData: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberFlags] memberFlags
 FSharp.Compiler.Syntax.SynValData: System.String ToString()
+FSharp.Compiler.Syntax.SynValInfo: Boolean IsSynValInfo
+FSharp.Compiler.Syntax.SynValInfo: Boolean get_IsSynValInfo()
 FSharp.Compiler.Syntax.SynValInfo: FSharp.Compiler.Syntax.SynArgInfo get_returnInfo()
 FSharp.Compiler.Syntax.SynValInfo: FSharp.Compiler.Syntax.SynArgInfo returnInfo
 FSharp.Compiler.Syntax.SynValInfo: FSharp.Compiler.Syntax.SynValInfo NewSynValInfo(Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynArgInfo]], FSharp.Compiler.Syntax.SynArgInfo)
@@ -9313,6 +9460,8 @@ FSharp.Compiler.Syntax.SynValInfo: Microsoft.FSharp.Collections.FSharpList`1[Mic
 FSharp.Compiler.Syntax.SynValInfo: Microsoft.FSharp.Collections.FSharpList`1[System.String] ArgNames
 FSharp.Compiler.Syntax.SynValInfo: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_ArgNames()
 FSharp.Compiler.Syntax.SynValInfo: System.String ToString()
+FSharp.Compiler.Syntax.SynValSig: Boolean IsSynValSig
+FSharp.Compiler.Syntax.SynValSig: Boolean get_IsSynValSig()
 FSharp.Compiler.Syntax.SynValSig: Boolean get_isInline()
 FSharp.Compiler.Syntax.SynValSig: Boolean get_isMutable()
 FSharp.Compiler.Syntax.SynValSig: Boolean isInline
@@ -9347,7 +9496,9 @@ FSharp.Compiler.Syntax.SynValSig: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Co
 FSharp.Compiler.Syntax.SynValSig: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr] get_synExpr()
 FSharp.Compiler.Syntax.SynValSig: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr] synExpr
 FSharp.Compiler.Syntax.SynValSig: System.String ToString()
+FSharp.Compiler.Syntax.SynValTyparDecls: Boolean IsSynValTyparDecls
 FSharp.Compiler.Syntax.SynValTyparDecls: Boolean canInfer
+FSharp.Compiler.Syntax.SynValTyparDecls: Boolean get_IsSynValTyparDecls()
 FSharp.Compiler.Syntax.SynValTyparDecls: Boolean get_canInfer()
 FSharp.Compiler.Syntax.SynValTyparDecls: FSharp.Compiler.Syntax.SynValTyparDecls NewSynValTyparDecls(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynTyparDecls], Boolean)
 FSharp.Compiler.Syntax.SynValTyparDecls: Int32 Tag
@@ -11718,37 +11869,6 @@ FSharp.Compiler.Xml.XmlDoc: System.String[] GetElaboratedXmlLines()
 FSharp.Compiler.Xml.XmlDoc: System.String[] UnprocessedLines
 FSharp.Compiler.Xml.XmlDoc: System.String[] get_UnprocessedLines()
 FSharp.Compiler.Xml.XmlDoc: Void .ctor(System.String[], FSharp.Compiler.Text.Range)
-FSharp.Compiler.Symbols.FSharpType: Boolean HasNullAnnotation
-FSharp.Compiler.Symbols.FSharpType: Boolean IsNullAmbivalent
-FSharp.Compiler.Symbols.FSharpType: Boolean get_HasNullAnnotation()
-FSharp.Compiler.Symbols.FSharpType: Boolean get_IsNullAmbivalent()
-FSharp.Compiler.Syntax.SynType+StaticConstantNull: FSharp.Compiler.Text.Range get_range()
-FSharp.Compiler.Syntax.SynType+StaticConstantNull: FSharp.Compiler.Text.Range range
-FSharp.Compiler.Syntax.SynType+Tags: Int32 StaticConstantNull
-FSharp.Compiler.Syntax.SynType+Tags: Int32 WithNull
-FSharp.Compiler.Syntax.SynType+WithNull: Boolean ambivalent
-FSharp.Compiler.Syntax.SynType+WithNull: Boolean get_ambivalent()
-FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Syntax.SynType get_innerType()
-FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Syntax.SynType innerType
-FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Text.Range get_range()
-FSharp.Compiler.Syntax.SynType+WithNull: FSharp.Compiler.Text.Range range
-FSharp.Compiler.Syntax.SynType: Boolean IsStaticConstantNull
-FSharp.Compiler.Syntax.SynType: Boolean IsWithNull
-FSharp.Compiler.Syntax.SynType: Boolean get_IsStaticConstantNull()
-FSharp.Compiler.Syntax.SynType: Boolean get_IsWithNull()
-FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewStaticConstantNull(FSharp.Compiler.Text.Range)
-FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewWithNull(FSharp.Compiler.Syntax.SynType, Boolean, FSharp.Compiler.Text.Range)
-FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+StaticConstantNull
-FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+WithNull
-FSharp.Compiler.Syntax.SynTypeConstraint+Tags: Int32 WhereTyparNotSupportsNull
-FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Syntax.SynTypar genericName
-FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Syntax.SynTypar get_genericName()
-FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Text.Range get_range()
-FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull: FSharp.Compiler.Text.Range range
-FSharp.Compiler.Syntax.SynTypeConstraint: Boolean IsWhereTyparNotSupportsNull
-FSharp.Compiler.Syntax.SynTypeConstraint: Boolean get_IsWhereTyparNotSupportsNull()
-FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint NewWhereTyparNotSupportsNull(FSharp.Compiler.Syntax.SynTypar, FSharp.Compiler.Text.Range)
-FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Syntax.SynTypeConstraint+WhereTyparNotSupportsNull
 Internal.Utilities.Library.DelayInitArrayMap`3[T,TDictKey,TDictValue]: System.Collections.Generic.IDictionary`2[TDictKey,TDictValue] CreateDictionary(T[])
 Internal.Utilities.Library.DelayInitArrayMap`3[T,TDictKey,TDictValue]: System.Collections.Generic.IDictionary`2[TDictKey,TDictValue] GetDictionary()
 Internal.Utilities.Library.DelayInitArrayMap`3[T,TDictKey,TDictValue]: T[] GetArray()
@@ -11760,4 +11880,4 @@ Internal.Utilities.Library.InterruptibleLazy`1[T]: Internal.Utilities.Library.In
 Internal.Utilities.Library.InterruptibleLazy`1[T]: T Force()
 Internal.Utilities.Library.InterruptibleLazy`1[T]: T Value
 Internal.Utilities.Library.InterruptibleLazy`1[T]: T get_Value()
-Internal.Utilities.Library.InterruptibleLazy`1[T]: Void .ctor(Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T])
+Internal.Utilities.Library.InterruptibleLazy`1[T]: Void .ctor(Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T])
\ No newline at end of file
diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs
index 55f03a4f9c1..d021fecc953 100644
--- a/tests/FSharp.Test.Utilities/Compiler.fs
+++ b/tests/FSharp.Test.Utilities/Compiler.fs
@@ -475,6 +475,9 @@ module rec Compiler =
         | FS fs -> FS { fs with OutputDirectory = path }
         | _ -> failwith "withOutputDirectory is only supported on F#"
 
+    let withCheckNulls (cUnit: CompilationUnit) : CompilationUnit =
+        withOptionsHelper ["--checknulls+"] "checknulls is only supported in F#" cUnit
+
     let withBufferWidth (width: int)(cUnit: CompilationUnit) : CompilationUnit =
         withOptionsHelper [ $"--bufferwidth:{width}" ] "withBufferWidth is only supported on F#" cUnit
 

From 00a591c66e6e22b68ab5d93c94b34c7d4fb7f2c4 Mon Sep 17 00:00:00 2001
From: Tomas Grosup 
Date: Tue, 23 Jan 2024 12:39:07 +0100
Subject: [PATCH 55/59] Nullness - include in QuickInfo and in general in
 "typeEnc" (string representation of a type) (#16555)

* failing test

* todo for IL import

* explanation added

* il meta parsing

* flags evaluation

* you shall passs

* evaluateFirstOrderNullnessAndAdvance

* import il type with nullness

* type import

* IL nullness import

fields, props, events, method args, method return types - nullness imported from IL

* test rename

* fantomas

* get stack trace on error

* split ilmethod's type

* fix crashes for Csharp style extensions

* solve coexistance of nullness and Is* properties of DUs

* updating tests

* clean tests

* fantomas

* fantomas one more time

* importing nullness for generic typars

* print failing ivals, let's see

* write even more!

* isolated failing test - combo of module rec, signature file, IVT

* another attempt

* format

* test

* hide tests

* Remove 'specialname' for DU case tester

* format

* warning as error

* update baseline netcore

* nullable errors not in desktop framework

* surface area, trimming

* surface area

* cosmetic cleanup & annotations

* Rename to ILMethParentTypeInfo

* making vMapFold tail recursive

* physical nullnessEquiv

* format

* Commenting SkipNullness usages

* Nullness work - activity module

* Remove strict generic 'T:null' import

* Null|NonNull pattern also for regular compilation

* Backported Null|NonNull active pattern

* one more time

* revert

* Show nullness in quickinfo and in general in type representations
---
 src/Compiler/Symbols/SymbolHelpers.fs  |  2 +-
 src/Compiler/TypedTree/TypedTree.fs    |  2 ++
 src/Compiler/TypedTree/TypedTree.fsi   |  2 ++
 src/Compiler/TypedTree/TypedTreeOps.fs | 24 ++++++++++++------------
 4 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/src/Compiler/Symbols/SymbolHelpers.fs b/src/Compiler/Symbols/SymbolHelpers.fs
index c5eded88ba7..8e69702800c 100644
--- a/src/Compiler/Symbols/SymbolHelpers.fs
+++ b/src/Compiler/Symbols/SymbolHelpers.fs
@@ -546,7 +546,7 @@ module internal SymbolHelpers =
     let SimplerDisplayEnv denv = 
         { denv with shortConstraints=true
                     showStaticallyResolvedTyparAnnotations=false
-                    showNullnessAnnotations = Some false
+                    showNullnessAnnotations = Some true
                     abbreviateAdditionalConstraints=false
                     suppressNestedTypes=true
                     maxMembers=Some EnvMisc2.maxMembers }
diff --git a/src/Compiler/TypedTree/TypedTree.fs b/src/Compiler/TypedTree/TypedTree.fs
index 5e7c01094d9..e377213c329 100644
--- a/src/Compiler/TypedTree/TypedTree.fs
+++ b/src/Compiler/TypedTree/TypedTree.fs
@@ -4227,6 +4227,8 @@ type Nullness =
 
    override n.ToString() = match n.Evaluate() with NullnessInfo.WithNull -> "?"  | NullnessInfo.WithoutNull -> "" | NullnessInfo.AmbivalentToNull -> "%"
 
+   member n.ToFsharpCodeString() = match n.Evaluate() with NullnessInfo.WithNull -> " | null "  | NullnessInfo.WithoutNull -> "" | NullnessInfo.AmbivalentToNull -> ""
+
 // Note, nullness variables are only created if the nullness checking feature is on
 []
 type NullnessVar() = 
diff --git a/src/Compiler/TypedTree/TypedTree.fsi b/src/Compiler/TypedTree/TypedTree.fsi
index 19a815daff9..a2f167130e6 100644
--- a/src/Compiler/TypedTree/TypedTree.fsi
+++ b/src/Compiler/TypedTree/TypedTree.fsi
@@ -3043,6 +3043,8 @@ type Nullness =
 
     member TryEvaluate: unit -> NullnessInfo voption
 
+    member ToFsharpCodeString: unit -> string
+
 []
 type NullnessVar =
     new: unit -> NullnessVar
diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs
index 71db5c461f2..1af0df92d43 100644
--- a/src/Compiler/TypedTree/TypedTreeOps.fs
+++ b/src/Compiler/TypedTree/TypedTreeOps.fs
@@ -8776,26 +8776,26 @@ let rec typeEnc g (gtpsType, gtpsMethod) ty =
         let ety = destNativePtrTy g ty
         typeEnc g (gtpsType, gtpsMethod) ety + "*"
 
-    | _ when isArrayTy g ty -> 
-        let tcref, tinst = destAppTy g ty
+    | TType_app (_, _, nullness) when isArrayTy g ty -> 
+        let tcref, tinst = destAppTy g ty        
         let rank = rankOfArrayTyconRef g tcref
         let arraySuffix = "[" + String.concat ", " (List.replicate (rank-1) "0:") + "]"
-        typeEnc g (gtpsType, gtpsMethod) (List.head tinst) + arraySuffix
+        typeEnc g (gtpsType, gtpsMethod) (List.head tinst) + arraySuffix + nullness.ToFsharpCodeString()
 
     | TType_ucase (_, tinst)   
     | TType_app (_, tinst, _) -> 
-        let tyName = 
+        let tyName,nullness = 
             let ty = stripTyEqnsAndMeasureEqns g ty
             match ty with
-            | TType_app (tcref, _tinst, _) -> 
+            | TType_app (tcref, _tinst, nullness) -> 
                 // Generic type names are (name + "`" + digits) where name does not contain "`".
                 // In XML doc, when used in type instances, these do not use the ticks.
                 let path = Array.toList (fullMangledPathToTyconRef tcref) @ [tcref.CompiledName]
-                textOfPath (List.map DemangleGenericTypeName path)
+                textOfPath (List.map DemangleGenericTypeName path),nullness
             | _ ->
                 assert false
                 failwith "impossible"
-        tyName + tyargsEnc g (gtpsType, gtpsMethod) tinst
+        tyName + tyargsEnc g (gtpsType, gtpsMethod) tinst + nullness.ToFsharpCodeString()
 
     | TType_anon (anonInfo, tinst) -> 
         sprintf "%s%s" anonInfo.ILTypeRef.FullName (tyargsEnc g (gtpsType, gtpsMethod) tinst)
@@ -8806,11 +8806,11 @@ let rec typeEnc g (gtpsType, gtpsMethod) ty =
         else 
             sprintf "System.Tuple%s"(tyargsEnc g (gtpsType, gtpsMethod) tys)
 
-    | TType_fun (domainTy, rangeTy, _) -> 
-        "Microsoft.FSharp.Core.FSharpFunc" + tyargsEnc g (gtpsType, gtpsMethod) [domainTy; rangeTy]
+    | TType_fun (domainTy, rangeTy, nullness) -> 
+        "Microsoft.FSharp.Core.FSharpFunc" + tyargsEnc g (gtpsType, gtpsMethod) [domainTy; rangeTy] + nullness.ToFsharpCodeString()
 
-    | TType_var (typar, _) -> 
-        typarEnc g (gtpsType, gtpsMethod) typar
+    | TType_var (typar, nullness) -> 
+        typarEnc g (gtpsType, gtpsMethod) typar + nullness.ToFsharpCodeString()
 
     | TType_measure _ -> "?"
 
@@ -8822,7 +8822,7 @@ and tyargsEnc g (gtpsType, gtpsMethod) args =
 
 let XmlDocArgsEnc g (gtpsType, gtpsMethod) argTys =
     if isNil argTys then "" 
-    else "(" + String.concat "," (List.map (typeEnc g (gtpsType, gtpsMethod)) argTys) + ")"
+    else "(" + String.concat "," (List.map (typeEnc g (gtpsType, gtpsMethod)) argTys) + ")"    
 
 let buildAccessPath (cp: CompilationPath option) =
     match cp with

From 38532afc905c900cdd56514d7b79cf7028a01c36 Mon Sep 17 00:00:00 2001
From: dotnet bot 
Date: Wed, 24 Jan 2024 08:25:32 -0800
Subject: [PATCH 56/59] Merge main to feature/nullness (#16539)

Merge of main + syntax conflict resolution + semantic conflict resolution
---
 .config/dotnet-tools.json                     |   44 +-
 .devcontainer/devcontainer.json               |    2 +-
 .fantomasignore                               |    1 -
 .git-blame-ignore-revs                        |    2 +
 .github/PULL_REQUEST_TEMPLATE.md              |   18 +-
 .github/workflows/check_release_notes.yml     |   35 +-
 .vscode/launch.json                           |   21 +-
 .vscode/tasks.json                            |  117 +-
 .../TaskPerf.Benchmarks-report-github.md      |   67 -
 Directory.Build.props                         |    4 +
 Directory.Build.targets                       |    3 -
 FSharp.Benchmarks.sln                         |  119 +
 VisualFSharp.sln                              |   15 -
 azure-pipelines.yml                           |   35 +-
 .../AssemblyCheck/SkipVerifyEmbeddedPdb.txt   |    1 -
 docs/content/fsdocs-theme.css                 |    3 +
 docs/fcs/syntax-visitor.fsx                   |  189 -
 docs/fcs/untypedtree-apis.fsx                 |  553 +++
 docs/img/favicon.ico                          |  Bin 0 -> 107697 bytes
 docs/perf-discussions-archive.md              |   55 +
 .../.FSharp.Compiler.Service/8.0.100.md       |    3 +
 .../.FSharp.Compiler.Service/8.0.200.md       |   21 +
 .../.FSharp.Compiler.Service/8.0.300.md       |   19 +
 docs/release-notes/.FSharp.Core/8.0.200.md    |    4 +
 docs/release-notes/.FSharp.Core/8.0.300.md    |    3 +
 docs/release-notes/.Language/8.0.md           |    3 +
 docs/release-notes/.Language/preview.md       |    9 +
 docs/release-notes/.VisualStudio/17.10.md     |    7 +
 docs/release-notes/.VisualStudio/17.9.md      |    3 +
 docs/release-notes/.aux/Common.fsx            |   50 +
 docs/release-notes/About.md                   |   62 +
 .../release-notes/FSharp.Compiler.Service.fsx |   47 +
 .../FSharp.Compiler.Service/8.0.200.md        |    5 -
 docs/release-notes/FSharp.Core.fsx            |   42 +
 docs/release-notes/FSharp.Core/8.0.200.md     |    1 -
 docs/release-notes/Language.fsx               |   35 +
 docs/release-notes/Language/preview.md        |    1 -
 docs/running-documentation-locally.md         |   46 +
 eng/SourceBuildPrebuiltBaseline.xml           |    2 -
 eng/Version.Details.xml                       |   32 +-
 eng/Versions.props                            |   38 +-
 eng/common/darc-init.ps1                      |    2 +-
 eng/common/darc-init.sh                       |    2 +-
 .../post-build/add-build-to-channel.ps1       |    2 +-
 eng/common/post-build/publish-using-darc.ps1  |    2 +-
 .../post-build/trigger-subscriptions.ps1      |    2 +-
 eng/common/sdk-task.ps1                       |    2 +-
 eng/common/templates/job/job.yml              |    2 +-
 .../templates/job/publish-build-assets.yml    |    4 +-
 .../templates/post-build/common-variables.yml |    2 +-
 .../templates/post-build/post-build.yml       |    4 +-
 eng/common/tools.ps1                          |   16 +-
 eng/common/tools.sh                           |    7 +-
 eng/restore-internal-tools.yml                |    4 +-
 global.json                                   |   10 +-
 src/Compiler/AbstractIL/il.fs                 |    2 +-
 src/Compiler/AbstractIL/ilwrite.fs            |   22 +-
 src/Compiler/Checking/AttributeChecking.fs    |    2 +-
 .../Checking/CheckComputationExpressions.fs   | 4118 +++++++++++------
 src/Compiler/Checking/CheckDeclarations.fs    |  180 +-
 src/Compiler/Checking/CheckExpressions.fs     |  127 +-
 src/Compiler/Checking/CheckExpressions.fsi    |    5 +-
 src/Compiler/Checking/CheckFormatStrings.fs   |    7 +-
 .../Checking/CheckIncrementalClasses.fs       |   22 +-
 .../Checking/CheckIncrementalClasses.fsi      |    2 +-
 src/Compiler/Checking/CheckPatterns.fs        |    6 +-
 src/Compiler/Checking/CheckPatterns.fsi       |    4 +-
 src/Compiler/Checking/ConstraintSolver.fs     |   71 +-
 src/Compiler/Checking/ConstraintSolver.fsi    |   55 -
 src/Compiler/Checking/FindUnsolved.fs         |    2 +-
 src/Compiler/Checking/InfoReader.fs           |   11 +-
 src/Compiler/Checking/MethodCalls.fs          |    2 +-
 src/Compiler/Checking/NameResolution.fs       |  295 +-
 src/Compiler/Checking/NameResolution.fsi      |   69 +-
 src/Compiler/Checking/NicePrint.fs            |    8 +-
 .../Checking/PatternMatchCompilation.fs       |   15 +-
 src/Compiler/Checking/PostInferenceChecks.fs  |   12 +-
 src/Compiler/Checking/QuotationTranslator.fs  |   22 +-
 src/Compiler/Checking/QuotationTranslator.fsi |   15 +-
 src/Compiler/Checking/SignatureHash.fs        |    2 +-
 src/Compiler/Checking/TailCallChecks.fs       |  168 +-
 src/Compiler/Checking/infos.fs                |   13 +-
 src/Compiler/Checking/infos.fsi               |    3 +-
 src/Compiler/CodeGen/IlxGen.fs                |    9 +-
 .../DependencyManager/DependencyProvider.fs   |    2 +-
 .../NativeDllResolveHandler.fs                |    3 +-
 src/Compiler/Driver/CompilerDiagnostics.fs    |   78 +-
 src/Compiler/Driver/CompilerImports.fs        |   23 +
 src/Compiler/Driver/CompilerOptions.fs        |   16 +-
 src/Compiler/Driver/CreateILModule.fs         |   19 +-
 src/Compiler/Driver/FxResolver.fs             |    8 +-
 .../GraphChecking/DependencyResolution.fs     |   15 +-
 .../GraphChecking/FileContentMapping.fs       |   48 +-
 src/Compiler/Driver/GraphChecking/Graph.fs    |   49 +-
 src/Compiler/Driver/GraphChecking/Graph.fsi   |    8 +-
 .../Driver/GraphChecking/GraphProcessing.fs   |  136 +-
 .../Driver/GraphChecking/GraphProcessing.fsi  |    9 +
 src/Compiler/Driver/GraphChecking/Types.fs    |    3 +
 src/Compiler/Driver/GraphChecking/Types.fsi   |    3 +
 src/Compiler/Driver/ParseAndCheckInputs.fs    |   82 +-
 src/Compiler/Driver/ParseAndCheckInputs.fsi   |   70 +
 src/Compiler/Driver/fsc.fs                    |    2 +-
 src/Compiler/FSComp.txt                       |    5 +-
 src/Compiler/FSStrings.resx                   |   17 +-
 src/Compiler/FSharp.Compiler.Service.fsproj   |   22 +-
 src/Compiler/Facilities/AsyncMemoize.fs       |  610 +++
 src/Compiler/Facilities/AsyncMemoize.fsi      |   81 +
 src/Compiler/Facilities/BuildGraph.fs         |    8 -
 src/Compiler/Facilities/CompilerLocation.fs   |    5 +-
 src/Compiler/Facilities/DiagnosticsLogger.fs  |    2 +-
 src/Compiler/Facilities/Hashing.fs            |   81 +
 src/Compiler/Facilities/Hashing.fsi           |   46 +
 src/Compiler/Facilities/prim-lexing.fs        |   50 +-
 src/Compiler/Facilities/prim-lexing.fsi       |   11 +
 src/Compiler/Interactive/fsi.fs               |    9 +-
 src/Compiler/Optimize/LowerStateMachines.fs   |    4 +-
 src/Compiler/Optimize/Optimizer.fs            |   37 +-
 src/Compiler/Service/BackgroundCompiler.fs    | 1680 +++++++
 src/Compiler/Service/BackgroundCompiler.fsi   |  224 +
 src/Compiler/Service/FSharpCheckerResults.fs  |   54 +-
 src/Compiler/Service/FSharpCheckerResults.fsi |   33 +-
 .../Service/FSharpParseFileResults.fs         |  591 +--
 src/Compiler/Service/FSharpProjectSnapshot.fs |  626 +++
 src/Compiler/Service/IncrementalBuild.fs      |   14 +-
 src/Compiler/Service/IncrementalBuild.fsi     |   25 +
 src/Compiler/Service/ItemKey.fs               |    1 -
 .../Service/SemanticClassification.fs         |    4 +-
 src/Compiler/Service/ServiceAnalysis.fs       | 1298 +-----
 src/Compiler/Service/ServiceAnalysis.fsi      |   12 -
 .../Service/ServiceDeclarationLists.fs        |   22 +-
 src/Compiler/Service/ServiceNavigation.fs     |   18 +-
 src/Compiler/Service/ServiceParseTreeWalk.fs  |  564 ++-
 src/Compiler/Service/ServiceParseTreeWalk.fsi |  166 +-
 src/Compiler/Service/ServiceParsedInputOps.fs |   52 +-
 src/Compiler/Service/SynExpr.fs               |  931 ++++
 src/Compiler/Service/SynExpr.fsi              |   15 +
 src/Compiler/Service/SynPat.fs                |  253 +
 src/Compiler/Service/SynPat.fsi               |   13 +
 src/Compiler/Service/TransparentCompiler.fs   | 2071 +++++++++
 src/Compiler/Service/TransparentCompiler.fsi  |  175 +
 src/Compiler/Service/service.fs               | 1362 +-----
 src/Compiler/Service/service.fsi              |   44 +
 src/Compiler/Symbols/Exprs.fs                 |    8 +-
 src/Compiler/Symbols/SymbolHelpers.fs         |   16 +-
 src/Compiler/Symbols/Symbols.fs               |   13 +-
 src/Compiler/SyntaxTree/LexFilter.fs          |    3 +-
 src/Compiler/SyntaxTree/ParseHelpers.fs       |    2 +-
 src/Compiler/SyntaxTree/PrettyNaming.fs       |    2 +-
 src/Compiler/SyntaxTree/SyntaxTree.fs         |    4 +-
 src/Compiler/SyntaxTree/SyntaxTree.fsi        |    4 +-
 src/Compiler/SyntaxTree/SyntaxTreeOps.fs      |    5 +-
 src/Compiler/SyntaxTree/XmlDoc.fs             |    2 +-
 src/Compiler/TypedTree/TcGlobals.fs           |   13 +-
 src/Compiler/TypedTree/TypedTree.fs           |   38 +-
 src/Compiler/TypedTree/TypedTree.fsi          |    8 +-
 src/Compiler/TypedTree/TypedTreeOps.fs        |   70 +-
 src/Compiler/TypedTree/TypedTreeOps.fsi       |   19 +-
 src/Compiler/TypedTree/TypedTreePickle.fs     |    4 +-
 src/Compiler/Utilities/Activity.fs            |    1 +
 src/Compiler/Utilities/Activity.fsi           |    2 +-
 src/Compiler/Utilities/Cancellable.fs         |   38 +-
 src/Compiler/Utilities/Cancellable.fsi        |    1 -
 src/Compiler/Utilities/FileSystem.fs          |   20 +-
 src/Compiler/Utilities/LruCache.fs            |  273 ++
 src/Compiler/Utilities/LruCache.fsi           |   52 +
 src/Compiler/Utilities/PathMap.fs             |    7 +-
 src/Compiler/Utilities/illib.fs               |   11 +-
 src/Compiler/Utilities/illib.fsi              |    6 +
 src/Compiler/Utilities/sformat.fs             |    8 +-
 src/Compiler/Utilities/sr.fs                  |    3 +-
 src/Compiler/pars.fsy                         |  128 +-
 src/Compiler/xlf/FSComp.txt.cs.xlf            |   53 +-
 src/Compiler/xlf/FSComp.txt.de.xlf            |   53 +-
 src/Compiler/xlf/FSComp.txt.es.xlf            |   53 +-
 src/Compiler/xlf/FSComp.txt.fr.xlf            |   53 +-
 src/Compiler/xlf/FSComp.txt.it.xlf            |   53 +-
 src/Compiler/xlf/FSComp.txt.ja.xlf            |   53 +-
 src/Compiler/xlf/FSComp.txt.ko.xlf            |   53 +-
 src/Compiler/xlf/FSComp.txt.pl.xlf            |   53 +-
 src/Compiler/xlf/FSComp.txt.pt-BR.xlf         |   53 +-
 src/Compiler/xlf/FSComp.txt.ru.xlf            |   53 +-
 src/Compiler/xlf/FSComp.txt.tr.xlf            |   53 +-
 src/Compiler/xlf/FSComp.txt.zh-Hans.xlf       |   53 +-
 src/Compiler/xlf/FSComp.txt.zh-Hant.xlf       |   53 +-
 src/Compiler/xlf/FSStrings.cs.xlf             |   39 +-
 src/Compiler/xlf/FSStrings.de.xlf             |   39 +-
 src/Compiler/xlf/FSStrings.es.xlf             |   39 +-
 src/Compiler/xlf/FSStrings.fr.xlf             |   39 +-
 src/Compiler/xlf/FSStrings.it.xlf             |   39 +-
 src/Compiler/xlf/FSStrings.ja.xlf             |   39 +-
 src/Compiler/xlf/FSStrings.ko.xlf             |   39 +-
 src/Compiler/xlf/FSStrings.pl.xlf             |   39 +-
 src/Compiler/xlf/FSStrings.pt-BR.xlf          |   39 +-
 src/Compiler/xlf/FSStrings.ru.xlf             |   39 +-
 src/Compiler/xlf/FSStrings.tr.xlf             |   39 +-
 src/Compiler/xlf/FSStrings.zh-Hans.xlf        |   39 +-
 src/Compiler/xlf/FSStrings.zh-Hant.xlf        |   39 +-
 src/FSharp.Core/Linq.fs                       |   14 +-
 src/FSharp.Core/Linq.fsi                      |    4 +-
 src/FSharp.Core/array.fs                      |  339 +-
 src/FSharp.Core/array.fsi                     |  334 +-
 src/FSharp.Core/async.fs                      |    6 +-
 src/FSharp.Core/async.fsi                     |   16 +-
 src/FSharp.Core/collections.fsi               |    4 +-
 src/FSharp.Core/event.fs                      |    2 +-
 src/FSharp.Core/event.fsi                     |    2 +-
 src/FSharp.Core/fslib-extra-pervasives.fs     |   22 +-
 src/FSharp.Core/fslib-extra-pervasives.fsi    |   22 +-
 src/FSharp.Core/list.fs                       |    4 +-
 src/FSharp.Core/list.fsi                      |    4 +-
 src/FSharp.Core/local.fs                      |    2 +-
 src/FSharp.Core/local.fsi                     |   38 +-
 src/FSharp.Core/map.fs                        |    4 +-
 src/FSharp.Core/map.fsi                       |    4 +-
 src/FSharp.Core/option.fsi                    |    4 +-
 src/FSharp.Core/prim-types-prelude.fsi        |    4 +-
 src/FSharp.Core/prim-types.fs                 |  326 +-
 src/FSharp.Core/prim-types.fsi                |   54 +-
 src/FSharp.Core/printf.fs                     |   16 +-
 src/FSharp.Core/printf.fsi                    |   10 +-
 src/FSharp.Core/quotations.fs                 |   24 +-
 src/FSharp.Core/quotations.fsi                |   13 +-
 src/FSharp.Core/reflect.fs                    |   78 +-
 src/FSharp.Core/reflect.fsi                   |   73 +-
 src/FSharp.Core/result.fsi                    |    4 +-
 src/FSharp.Core/resumable.fs                  |    8 +-
 src/FSharp.Core/seq.fs                        |   10 +-
 src/FSharp.Core/seq.fsi                       |   12 +-
 src/FSharp.Core/seqcore.fs                    |    4 +-
 src/FSharp.Core/seqcore.fsi                   |    4 +-
 src/FSharp.Core/set.fs                        |    2 +-
 src/FSharp.Core/set.fsi                       |    6 +-
 src/FSharp.Core/string.fs                     |    4 +-
 .../Microsoft.FSharp.Compiler.fsproj          |    7 -
 src/fsc/fsc.targets                           |    8 -
 src/fsi/fsi.targets                           |    7 -
 .../SelfContained_Trimming_Test.fsproj        |    1 -
 ...taticLinkedFSharpCore_Trimming_Test.fsproj |    1 -
 tests/AheadOfTime/Trimming/check.ps1          |    2 +-
 .../CompilerService/AsyncLock.fs              |   26 +
 .../CompilerService/AsyncMemoize.fs           |  542 +++
 .../CompilerService/LruCache.fs               |  197 +
 .../E_NotMemberOrFunction01.fsx               |    2 +-
 .../CustomOperations.fs                       |   43 +
 .../ObjectExpressions/ObjectExpressions.fs    |    1 +
 .../ConstraintSolver/MemberConstraints.fs     |   40 +
 .../Nullness/NullAsTrueValue.fs.il.net472.bsl |    6 +-
 .../NullAsTrueValue.fs.il.netcore.bsl         |    6 +-
 .../EmittedIL/VeryLargeClasses.fs             |   50 +
 .../ExtendedDiagnosticDataTests.fs            |   16 +-
 .../ErrorMessages/TailCallAttribute.fs        |   26 +
 .../FSharp.Compiler.ComponentTests.fsproj     |   17 +-
 .../FSharpChecker/CommonWorkflows.fs          |   11 +-
 .../FSharpChecker/FindReferences.fs           |   12 +-
 .../FSharpChecker/ProjectSnapshot.fs          |  104 +
 .../FSharpChecker/TransparentCompiler.fs      |  803 ++++
 .../Language/DiscriminatedUnionTests.fs       |   14 +
 .../Language/ExtensionMethodTests.fs          |   37 +
 .../Language/SequenceExpressionTests.fs       |    3 +-
 .../Signatures/MissingDiagnostic.fs           |   24 +-
 .../TypeChecks/Graph/Scenarios.fs             |  110 +
 .../TypeChecks/Graph/TypedTreeGraph.fs        |    4 +-
 .../TypeChecks/TyparNameTests.fs              |    2 +-
 ...ervice.SurfaceArea.netstandard20.debug.bsl |  189 +-
 ...vice.SurfaceArea.netstandard20.release.bsl |  189 +-
 .../FSharp.Compiler.Service.Tests.fsproj      |   10 +-
 .../SynExprTests.fs                           |   88 +
 .../SynPatTests.fs                            |   36 +
 .../UnnecessaryParenthesesTests.fs            |   52 -
 .../FSharp.Compiler.UnitTests.fsproj          |    1 +
 .../ParsedInputModuleTests.fs                 |  449 ++
 ...p.Core.SurfaceArea.netstandard20.debug.bsl |    3 +
 ...Core.SurfaceArea.netstandard20.release.bsl |    1 +
 ...p.Core.SurfaceArea.netstandard21.debug.bsl |    3 +
 ...Core.SurfaceArea.netstandard21.release.bsl |    1 +
 tests/FSharp.Test.Utilities/Compiler.fs       |    6 +-
 tests/FSharp.Test.Utilities/CompilerAssert.fs |   31 +-
 .../FSharp.Test.Utilities.fsproj              |   13 +
 .../ProjectGeneration.fs                      |  122 +-
 tests/FSharp.Test.Utilities/TestFramework.fs  |    5 +-
 tests/FSharp.Test.Utilities/Utilities.fs      |   19 +-
 .../CompiledCodeBenchmarks/MicroPerf/Async.fs |    2 +-
 .../MicroPerf/Benchmarks.fs                   |   11 +-
 .../MicroPerf/CS/MicroPerfCSharp.cs           |    2 +-
 .../MicroPerf/CS/MicroPerfCSharp.csproj       |    9 +-
 .../MicroPerf/Collections.fs                  |    6 +-
 .../MicroPerf/MicroPerf.fsproj                |   15 +-
 .../TaskPerf/TaskPerf/TaskPerf.fs             |    8 -
 .../TaskPerf/TaskPerf/TaskPerf.fsproj         |   17 +-
 .../TaskPerfCSharp/TaskPerfCSharp.csproj      |    9 +-
 .../TaskPerfPreviousCompiler.fsproj           |   30 -
 .../TaskPerf/TaskPerfPreviousCompiler/defs.fs |   14 -
 .../HistoricalBenchmark.fsproj                |    7 -
 .../BackgroundCompilerBenchmarks.fs           |  227 +-
 .../CompilerServiceBenchmarks/Benchmarks.fs   |    1 -
 .../CompilerServiceBenchmarks.fs              |    6 +-
 .../ComputationExpressionBenchmarks.fs        |   53 +
 .../DecentlySizedStandAloneFileBenchmark.fs   |   65 +-
 .../FSharp.Compiler.Benchmarks.fsproj         |   10 +-
 .../FileCascadeBenchmarks.fs                  |    2 +-
 .../benchmarks.ipynb                          |  117 -
 .../ce/CE100xnest1.fs                         |  115 +
 .../ce/CE100xnest10.fs                        | 3616 +++++++++++++++
 .../ce/CE100xnest5.fs                         | 1615 +++++++
 .../ce/CE200xnest5.fs                         | 3615 +++++++++++++++
 .../ce/CEwCO100xnest5.fs                      | 2937 ++++++++++++
 .../ce/CEwCO500xnest1.fs                      |  539 +++
 .../FCSSourceFiles/FCSSourceFiles.fsproj      |    1 +
 .../FCSBenchmarks/FCSSourceFiles/Program.fs   |    7 +-
 .../Fsharp.ProfilingStartpointProject.fsproj  |   16 -
 .../Program.fs                                |   47 -
 .../Libraries/Core/Operators/AbsTests.fs      |   14 +-
 .../Libraries/Core/Operators/SignTests.fs     |    8 +-
 tests/fsharp/typecheck/sigs/neg06.bsl         |   16 +-
 tests/fsharp/typecheck/sigs/neg61.bsl         |    2 +-
 .../ExpressionQuotations/Baselines/E_Cast.fs  |    3 +-
 .../ConstraintSolving/E_ValueRestriction01.fs |   17 +-
 .../E_GenInterfaceWGenMethods01.fs            |    2 +-
 .../E_NotMemberOrFunction01.fsx               |    4 +-
 .../EnumTypes/E_NoMethodsOnEnums01.fs         |    5 +-
 .../E_InvalidRecursiveGeneric01.fs            |    2 +-
 .../E_InvalidRecursiveGeneric02.fs            |    2 +-
 .../StructTypes/E_StructConstruction03.fs     |    4 +-
 .../W_NonGenVarInValueRestrictionWarning.fs   |    4 +-
 .../Diagnostics/NONTERM/tuplewithlazy01.fs    |    4 +-
 .../Diagnostics/NONTERM/tuplewithlazy01b.fs   |    4 +-
 .../LocalCompilerAndFslib.fsproj              |   23 +
 .../Program.fs                                |   25 +
 .../SelfDefinedTailCallAttribute/Attribute.fs |    6 +
 .../SelfDefinedTailCallAttribute/Program.fs   |   13 +
 .../tailcallaltattr.fsproj                    |   20 +
 tests/service/Common.fs                       |   10 +-
 tests/service/ExprTests.fs                    |   71 +-
 .../service/ModuleReaderCancellationTests.fs  |    2 +-
 tests/service/MultiProjectAnalysisTests.fs    |  115 +-
 tests/service/PatternMatchCompilationTests.fs |   52 +-
 tests/service/ProjectAnalysisTests.fs         |  368 +-
 tests/service/ScriptOptionsTests.fs           |    4 +-
 tests/service/ServiceUntypedParseTests.fs     |    2 +-
 tests/service/Symbols.fs                      |   80 +
 ...uldBeIncludedInSecondaryConstructor.fs.bsl |    4 +-
 ...lSignShouldBePresentInMemberBinding.fs.bsl |    4 +-
 ...resentInMemberBindingWithParameters.fs.bsl |    4 +-
 ...resentInMemberBindingWithReturnType.fs.bsl |    4 +-
 ...fEqualSignShouldBePresentInProperty.fs.bsl |    4 +-
 .../Expression/Object - Class 08.fs.bsl       |    2 +-
 .../Expression/Object - Class 13.fs.bsl       |    2 +-
 .../Expression/SynExprObjWithSetter.fs.bsl    |    4 +-
 .../Unfinished escaped ident 02.fs.bsl        |    4 +-
 .../LeadingKeyword/NewKeyword.fs.bsl          |    4 +-
 .../SyntaxTree/Member/Auto property 07.fs.bsl |    4 +-
 .../SyntaxTree/Member/GetSetMember 01.fs.bsl  |    4 +-
 .../Implicit ctor - Missing type 01.fs.bsl    |   20 +-
 .../Implicit ctor - Missing type 02.fs.bsl    |   35 +-
 .../Member/Implicit ctor - Pat - Tuple 01.fs  |    3 +
 .../Implicit ctor - Pat - Tuple 01.fs.bsl     |   76 +
 .../Member/Implicit ctor - Pat - Tuple 02.fs  |    3 +
 .../Implicit ctor - Pat - Tuple 02.fs.bsl     |   52 +
 .../Implicit ctor - Type - Fun 01.fs.bsl      |   34 +-
 .../Implicit ctor - Type - Fun 02.fs.bsl      |   43 +-
 .../Implicit ctor - Type - Fun 03.fs.bsl      |   43 +-
 .../Implicit ctor - Type - Fun 04.fs.bsl      |   34 +-
 .../Implicit ctor - Type - Fun 05.fs.bsl      |   43 +-
 .../Implicit ctor - Type - Fun 06.fs.bsl      |   56 +-
 .../Implicit ctor - Type - Tuple 01.fs.bsl    |   47 +-
 .../Implicit ctor - Type - Tuple 02.fs.bsl    |   54 +-
 .../Implicit ctor - Type - Tuple 03.fs.bsl    |   44 +-
 .../Implicit ctor - Type - Tuple 04.fs.bsl    |   51 +-
 .../Implicit ctor - Type - Tuple 05.fs.bsl    |   51 +-
 .../Member/ImplicitCtorWithAsKeyword.fs.bsl   |   98 +-
 .../data/SyntaxTree/Member/Member 03.fs.bsl   |    2 +-
 .../data/SyntaxTree/Member/Member 07.fs.bsl   |    2 +-
 .../data/SyntaxTree/Member/Member 12.fs.bsl   |    2 +-
 ...berContainsTheRangeOfTheWithKeyword.fs.bsl |    4 +-
 ...berContainsTheRangeOfTheWithKeyword.fs.bsl |    4 +-
 ...lotContainsTheRangeOfTheWithKeyword.fs.bsl |    4 +-
 ...ertyContainsTheRangeOfTheEqualsSign.fs.bsl |   57 +-
 ...rtyContainsTheRangeOfTheWithKeyword.fs.bsl |    4 +-
 .../SynTypeDefnWithMemberWithSetget.fs.bsl    |    4 +-
 ...berContainsTheRangeOfTheWithKeyword.fs.bsl |    4 +-
 .../Nullness/AbstractClassProperty.fs.bsl     |    4 +-
 .../Nullness/SignatureInAbstractMember.fs.bsl |    4 +-
 ...ivePatternIdentifierInPrivateMember.fs.bsl |    4 +-
 .../ObjectModelWithTwoMembers.fs.bsl          |    4 +-
 ...ePatternDefinitionWithoutParameters.fs.bsl |    2 +-
 .../service/data/SyntaxTree/Pattern/As 01.fs  |    4 +
 .../data/SyntaxTree/Pattern/As 01.fs.bsl      |   22 +
 .../service/data/SyntaxTree/Pattern/As 02.fs  |    4 +
 .../data/SyntaxTree/Pattern/As 02.fs.bsl      |   24 +
 .../service/data/SyntaxTree/Pattern/As 03.fs  |    3 +
 .../data/SyntaxTree/Pattern/As 03.fs.bsl      |   21 +
 .../service/data/SyntaxTree/Pattern/As 04.fs  |    3 +
 .../data/SyntaxTree/Pattern/As 04.fs.bsl      |   23 +
 .../service/data/SyntaxTree/Pattern/As 05.fs  |    4 +
 .../data/SyntaxTree/Pattern/As 05.fs.bsl      |   25 +
 .../service/data/SyntaxTree/Pattern/As 06.fs  |    3 +
 .../data/SyntaxTree/Pattern/As 06.fs.bsl      |   24 +
 .../service/data/SyntaxTree/Pattern/As 07.fs  |    5 +
 .../data/SyntaxTree/Pattern/As 07.fs.bsl      |   25 +
 .../service/data/SyntaxTree/Pattern/As 08.fs  |    5 +
 .../data/SyntaxTree/Pattern/As 08.fs.bsl      |   23 +
 .../service/data/SyntaxTree/Pattern/As 09.fs  |    5 +
 .../data/SyntaxTree/Pattern/As 09.fs.bsl      |   36 +
 .../service/data/SyntaxTree/Pattern/As 10.fs  |    3 +
 .../data/SyntaxTree/Pattern/As 10.fs.bsl      |   25 +
 .../service/data/SyntaxTree/Pattern/As 11.fs  |    3 +
 .../data/SyntaxTree/Pattern/As 11.fs.bsl      |   28 +
 .../Pattern/Typed - Missing type 01.fs.bsl    |   10 +-
 .../Pattern/Typed - Missing type 05.fs.bsl    |   15 +-
 .../SimplePats/SimplePats 02.fs.bsl           |  165 +-
 .../service/data/SyntaxTree/Type/As 01.fs.bsl |    4 +-
 .../service/data/SyntaxTree/Type/As 02.fs.bsl |    4 +-
 .../service/data/SyntaxTree/Type/As 05.fs.bsl |    2 +-
 .../service/data/SyntaxTree/Type/As 06.fs.bsl |    2 +-
 .../service/data/SyntaxTree/Type/As 07.fs.bsl |    2 +-
 .../service/data/SyntaxTree/Type/As 08.fs.bsl |    2 +-
 .../data/SyntaxTree/Type/Class 03.fs.bsl      |    4 +-
 .../data/SyntaxTree/Type/Class 04.fs.bsl      |    4 +-
 .../data/SyntaxTree/Type/Class 05.fs.bsl      |    8 +-
 tests/service/data/SyntaxTree/Type/Enum 01.fs |    6 +
 .../data/SyntaxTree/Type/Enum 01.fs.bsl       |   28 +
 tests/service/data/SyntaxTree/Type/Enum 02.fs |    6 +
 .../data/SyntaxTree/Type/Enum 02.fs.bsl       |   27 +
 tests/service/data/SyntaxTree/Type/Enum 03.fs |    6 +
 .../data/SyntaxTree/Type/Enum 03.fs.bsl       |   31 +
 tests/service/data/SyntaxTree/Type/Enum 04.fs |    7 +
 .../data/SyntaxTree/Type/Enum 04.fs.bsl       |   37 +
 tests/service/data/SyntaxTree/Type/Enum 05.fs |    6 +
 .../data/SyntaxTree/Type/Enum 05.fs.bsl       |   31 +
 tests/service/data/SyntaxTree/Type/Enum 06.fs |    7 +
 .../data/SyntaxTree/Type/Enum 06.fs.bsl       |   37 +
 .../data/SyntaxTree/Type/Enum 07 - Eof.fs     |    4 +
 .../data/SyntaxTree/Type/Enum 07 - Eof.fs.bsl |   30 +
 .../data/SyntaxTree/Type/Enum 08 - Eof.fs     |    4 +
 .../data/SyntaxTree/Type/Enum 08 - Eof.fs.bsl |   30 +
 .../data/SyntaxTree/Type/Enum 09 - Eof.fs     |    4 +
 .../data/SyntaxTree/Type/Enum 09 - Eof.fs.bsl |   30 +
 .../data/SyntaxTree/Type/Enum 10 - Eof.fs     |    4 +
 .../data/SyntaxTree/Type/Enum 10 - Eof.fs.bsl |   30 +
 .../SyntaxTree/Type/Primary ctor 01.fs.bsl    |    4 +-
 .../SyntaxTree/Type/Primary ctor 02.fs.bsl    |    4 +-
 .../SyntaxTree/Type/Primary ctor 03.fs.bsl    |    2 +-
 .../SyntaxTree/Type/Primary ctor 04.fs.bsl    |    4 +-
 .../SyntaxTree/Type/Primary ctor 05.fs.bsl    |    2 +-
 ...aceContainsTheRangeOfTheWithKeyword.fs.bsl |    4 +-
 .../data/SyntaxTree/Type/Type 11.fs.bsl       |    4 +-
 vsintegration/readme.md                       |    4 +
 .../FSharp.Editor/Common/CancellableTasks.fs  |   10 +
 .../src/FSharp.Editor/Common/Extensions.fs    |    8 +-
 .../src/FSharp.Editor/Common/Logging.fs       |    5 +-
 .../Completion/CompletionProvider.fs          |   18 +-
 .../Completion/CompletionService.fs           |    2 +-
 .../FSharp.Editor/Completion/SignatureHelp.fs |   48 +-
 ...nnecessaryParenthesesDiagnosticAnalyzer.fs |   31 +-
 .../DocComments/XMLDocumentation.fs           |   71 +-
 .../src/FSharp.Editor/FSharp.Editor.fsproj    |    1 +
 .../src/FSharp.Editor/FSharp.Editor.resx      |   13 +-
 .../LanguageService/LanguageService.fs        |   26 +-
 .../LanguageService/SymbolHelpers.fs          |   13 +-
 .../LanguageService/WorkspaceExtensions.fs    |  441 +-
 .../FSharp.Editor/Options/EditorOptions.fs    |   17 +
 .../QuickInfo/QuickInfoProvider.fs            |    7 +-
 .../FSharp.Editor/Refactor/AddReturnType.fs   |  118 +
 .../Telemetry/TelemetryReporter.fs            |    4 +-
 .../FSharp.Editor/xlf/FSharp.Editor.cs.xlf    |   21 +-
 .../FSharp.Editor/xlf/FSharp.Editor.de.xlf    |   21 +-
 .../FSharp.Editor/xlf/FSharp.Editor.es.xlf    |   21 +-
 .../FSharp.Editor/xlf/FSharp.Editor.fr.xlf    |   21 +-
 .../FSharp.Editor/xlf/FSharp.Editor.it.xlf    |   21 +-
 .../FSharp.Editor/xlf/FSharp.Editor.ja.xlf    |   21 +-
 .../FSharp.Editor/xlf/FSharp.Editor.ko.xlf    |   21 +-
 .../FSharp.Editor/xlf/FSharp.Editor.pl.xlf    |   21 +-
 .../FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf |   21 +-
 .../FSharp.Editor/xlf/FSharp.Editor.ru.xlf    |   21 +-
 .../FSharp.Editor/xlf/FSharp.Editor.tr.xlf    |   21 +-
 .../xlf/FSharp.Editor.zh-Hans.xlf             |   21 +-
 .../xlf/FSharp.Editor.zh-Hant.xlf             |   21 +-
 .../AdvancedOptionsControl.xaml               |   11 +
 ...nguageServicePerformanceOptionControl.xaml |   24 +-
 .../QuickInfoOptionControl.xaml               |   50 +-
 .../FSharp.UIResources/Strings.Designer.cs    |   81 +
 .../src/FSharp.UIResources/Strings.resx       |   27 +
 .../src/FSharp.UIResources/xlf/Strings.cs.xlf |   51 +-
 .../src/FSharp.UIResources/xlf/Strings.de.xlf |   51 +-
 .../src/FSharp.UIResources/xlf/Strings.es.xlf |   51 +-
 .../src/FSharp.UIResources/xlf/Strings.fr.xlf |   51 +-
 .../src/FSharp.UIResources/xlf/Strings.it.xlf |   51 +-
 .../src/FSharp.UIResources/xlf/Strings.ja.xlf |   51 +-
 .../src/FSharp.UIResources/xlf/Strings.ko.xlf |   51 +-
 .../src/FSharp.UIResources/xlf/Strings.pl.xlf |   51 +-
 .../FSharp.UIResources/xlf/Strings.pt-BR.xlf  |   51 +-
 .../src/FSharp.UIResources/xlf/Strings.ru.xlf |   51 +-
 .../src/FSharp.UIResources/xlf/Strings.tr.xlf |   51 +-
 .../xlf/Strings.zh-Hans.xlf                   |   51 +-
 .../xlf/Strings.zh-Hant.xlf                   |   51 +-
 .../RemoveUnnecessaryParenthesesTests.fs      |   31 +-
 .../FSharp.Editor.Tests.fsproj                |    3 +
 .../Helpers/RoslynHelpers.fs                  |    5 +
 .../FSharp.Editor.Tests/QuickInfoTests.fs     |    6 +-
 .../Refactors/AddReturnTypeTests.fs           |  452 ++
 .../Refactors/RefactorTestFramework.fs        |   89 +
 .../SignatureHelpProviderTests.fs             |   47 +-
 502 files changed, 35311 insertions(+), 8785 deletions(-)
 create mode 100644 .git-blame-ignore-revs
 delete mode 100644 BenchmarkDotNet.Artifacts/results/TaskPerf.Benchmarks-report-github.md
 create mode 100644 FSharp.Benchmarks.sln
 create mode 100644 docs/content/fsdocs-theme.css
 delete mode 100644 docs/fcs/syntax-visitor.fsx
 create mode 100644 docs/fcs/untypedtree-apis.fsx
 create mode 100644 docs/img/favicon.ico
 create mode 100644 docs/perf-discussions-archive.md
 create mode 100644 docs/release-notes/.FSharp.Compiler.Service/8.0.100.md
 create mode 100644 docs/release-notes/.FSharp.Compiler.Service/8.0.200.md
 create mode 100644 docs/release-notes/.FSharp.Compiler.Service/8.0.300.md
 create mode 100644 docs/release-notes/.FSharp.Core/8.0.200.md
 create mode 100644 docs/release-notes/.FSharp.Core/8.0.300.md
 create mode 100644 docs/release-notes/.Language/8.0.md
 create mode 100644 docs/release-notes/.Language/preview.md
 create mode 100644 docs/release-notes/.VisualStudio/17.10.md
 create mode 100644 docs/release-notes/.VisualStudio/17.9.md
 create mode 100644 docs/release-notes/.aux/Common.fsx
 create mode 100644 docs/release-notes/About.md
 create mode 100644 docs/release-notes/FSharp.Compiler.Service.fsx
 delete mode 100644 docs/release-notes/FSharp.Compiler.Service/8.0.200.md
 create mode 100644 docs/release-notes/FSharp.Core.fsx
 delete mode 100644 docs/release-notes/FSharp.Core/8.0.200.md
 create mode 100644 docs/release-notes/Language.fsx
 delete mode 100644 docs/release-notes/Language/preview.md
 create mode 100644 docs/running-documentation-locally.md
 create mode 100644 src/Compiler/Facilities/AsyncMemoize.fs
 create mode 100644 src/Compiler/Facilities/AsyncMemoize.fsi
 create mode 100644 src/Compiler/Facilities/Hashing.fs
 create mode 100644 src/Compiler/Facilities/Hashing.fsi
 create mode 100644 src/Compiler/Service/BackgroundCompiler.fs
 create mode 100644 src/Compiler/Service/BackgroundCompiler.fsi
 create mode 100644 src/Compiler/Service/FSharpProjectSnapshot.fs
 create mode 100644 src/Compiler/Service/SynExpr.fs
 create mode 100644 src/Compiler/Service/SynExpr.fsi
 create mode 100644 src/Compiler/Service/SynPat.fs
 create mode 100644 src/Compiler/Service/SynPat.fsi
 create mode 100644 src/Compiler/Service/TransparentCompiler.fs
 create mode 100644 src/Compiler/Service/TransparentCompiler.fsi
 create mode 100644 src/Compiler/Utilities/LruCache.fs
 create mode 100644 src/Compiler/Utilities/LruCache.fsi
 create mode 100644 tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncLock.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/CompilerService/LruCache.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ComputationExpressions/CustomOperations.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/VeryLargeClasses.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/FSharpChecker/ProjectSnapshot.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
 create mode 100644 tests/FSharp.Compiler.Service.Tests/SynExprTests.fs
 create mode 100644 tests/FSharp.Compiler.Service.Tests/SynPatTests.fs
 delete mode 100644 tests/FSharp.Compiler.Service.Tests/UnnecessaryParenthesesTests.fs
 create mode 100644 tests/FSharp.Compiler.UnitTests/ParsedInputModuleTests.fs
 delete mode 100644 tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerfPreviousCompiler/TaskPerfPreviousCompiler.fsproj
 delete mode 100644 tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerfPreviousCompiler/defs.fs
 delete mode 100644 tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/Benchmarks.fs
 create mode 100644 tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ComputationExpressionBenchmarks.fs
 delete mode 100644 tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/benchmarks.ipynb
 create mode 100644 tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE100xnest1.fs
 create mode 100644 tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE100xnest10.fs
 create mode 100644 tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE100xnest5.fs
 create mode 100644 tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE200xnest5.fs
 create mode 100644 tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CEwCO100xnest5.fs
 create mode 100644 tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CEwCO500xnest1.fs
 delete mode 100644 tests/benchmarks/Fsharp.ProfilingStartpointProject/Fsharp.ProfilingStartpointProject.fsproj
 delete mode 100644 tests/benchmarks/Fsharp.ProfilingStartpointProject/Program.fs
 create mode 100644 tests/projects/Sample_Local_Compiler_and_FSLib/LocalCompilerAndFslib.fsproj
 create mode 100644 tests/projects/Sample_Local_Compiler_and_FSLib/Program.fs
 create mode 100644 tests/projects/misc/SelfDefinedTailCallAttribute/Attribute.fs
 create mode 100644 tests/projects/misc/SelfDefinedTailCallAttribute/Program.fs
 create mode 100644 tests/projects/misc/SelfDefinedTailCallAttribute/tailcallaltattr.fsproj
 create mode 100644 tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 01.fs
 create mode 100644 tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 01.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 02.fs
 create mode 100644 tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 02.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 01.fs
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 01.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 02.fs
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 02.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 03.fs
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 03.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 04.fs
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 04.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 05.fs
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 05.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 06.fs
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 06.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 07.fs
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 07.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 08.fs
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 08.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 09.fs
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 09.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 10.fs
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 10.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 11.fs
 create mode 100644 tests/service/data/SyntaxTree/Pattern/As 11.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 01.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 01.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 02.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 02.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 03.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 03.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 04.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 04.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 05.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 05.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 06.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 06.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 07 - Eof.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 07 - Eof.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 08 - Eof.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 08 - Eof.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 09 - Eof.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 09 - Eof.fs.bsl
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 10 - Eof.fs
 create mode 100644 tests/service/data/SyntaxTree/Type/Enum 10 - Eof.fs.bsl
 create mode 100644 vsintegration/src/FSharp.Editor/Refactor/AddReturnType.fs
 create mode 100644 vsintegration/tests/FSharp.Editor.Tests/Refactors/AddReturnTypeTests.fs
 create mode 100644 vsintegration/tests/FSharp.Editor.Tests/Refactors/RefactorTestFramework.fs

diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 506d284412a..4dbfc605554 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -1,12 +1,48 @@
 {
-  "version": 1,
   "isRoot": true,
   "tools": {
+    "dotnet-counters": {
+      "commands": [
+        "dotnet-counters"
+      ],
+      "version": "8.0.460601"
+    },
+    "dotnet-dump": {
+      "commands": [
+        "dotnet-dump"
+      ],
+      "version": "8.0.460601"
+    },
+    "dotnet-gcdump": {
+      "commands": [
+        "dotnet-gcdump"
+      ],
+      "version": "8.0.460601"
+    },
+    "dotnet-sos": {
+      "commands": [
+        "dotnet-sos"
+      ],
+      "version": "8.0.460601"
+    },
+    "dotnet-symbol": {
+      "commands": [
+        "dotnet-symbol"
+      ],
+      "version": "1.0.460401"
+    },
+    "dotnet-trace": {
+      "commands": [
+        "dotnet-trace"
+      ],
+      "version": "8.0.460601"
+    },
     "fantomas": {
-      "version": "6.2.3",
       "commands": [
         "fantomas"
-      ]
+      ],
+      "version": "6.2.3"
     }
-  }
+  },
+  "version": 1
 }
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 5cf08aea407..44cf398c407 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -1,7 +1,7 @@
 // For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
 {
     "name": "F#",
-    "image": "mcr.microsoft.com/dotnet/sdk:8.0.100-rc.1",
+    "image": "mcr.microsoft.com/dotnet/sdk:8.0",
     "features": {
         "ghcr.io/devcontainers/features/common-utils:2": {},
         "ghcr.io/devcontainers/features/git:1": {},
diff --git a/.fantomasignore b/.fantomasignore
index a22c6c9249d..6b568034be7 100644
--- a/.fantomasignore
+++ b/.fantomasignore
@@ -20,7 +20,6 @@ src/Compiler/Checking/AccessibilityLogic.fs
 src/Compiler/Checking/AttributeChecking.fs
 src/Compiler/Checking/AugmentWithHashCompare.fs
 src/Compiler/Checking/CheckBasics.fs
-src/Compiler/Checking/CheckComputationExpressions.fs
 src/Compiler/Checking/CheckDeclarations.fs
 src/Compiler/Checking/CheckExpressions.fs
 src/Compiler/Checking/CheckFormatStrings.fs
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644
index 00000000000..d8110ac0ace
--- /dev/null
+++ b/.git-blame-ignore-revs
@@ -0,0 +1,2 @@
+# Format src/Compiler/Checking/CheckComputationExpressions.fs, https://github.com/dotnet/fsharp/pull/16512
+603a310cdfd9902ec1d29b399377dcc9ac56235b
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 6642e4b7df6..f3fc39c1ec7 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -9,17 +9,17 @@ Fixes # (issue, if applicable)
 - [ ] Test cases added
 - [ ] Performance benchmarks added in case of performance changes
 - [ ] Release notes entry updated:
-    > Please make sure to add an entry with short succint description of the change as well as link to this pull request to the respective release notes file, if applicable.
+    > Please make sure to add an entry with short succinct description of the change as well as link to this pull request to the respective release notes file, if applicable.
     >
     > Release notes files:
-    > - If anything under `src/Compiler` has been changed, please make sure to make an entry in `docs/release-notes/FSharp.Compiler.Service/.md`, where `` is usually "highest" one, e.g. `42.8.200`
-    > - If language feature was added (i.e. `LanguageFeatures.fsi` was changed), please add it to `docs/releae-notes/Language/preview.md`
-    > - If a change to `FSharp.Core` was made, please make sure to edit `docs/release-notes/FSharp.Core/.md` where version is "highest" one, e.g. `8.0.200`.
+    > - If anything under `src/Compiler` has been changed, please make sure to make an entry in `docs/release-notes/.FSharp.Compiler.Service/.md`, where `` is usually "highest" one, e.g. `42.8.200`
+    > - If language feature was added (i.e. `LanguageFeatures.fsi` was changed), please add it to `docs/releae-notes/.Language/preview.md`
+    > - If a change to `FSharp.Core` was made, please make sure to edit `docs/release-notes/.FSharp.Core/.md` where version is "highest" one, e.g. `8.0.200`.
 
-    > Examples of release notes entries:
-    > - Respect line limit in quick info popup - https://github.com/dotnet/fsharp/pull/16208
-    > - More inlines for Result module - https://github.com/dotnet/fsharp/pull/16106
-    > - Miscellaneous fixes to parens analysis - https://github.com/dotnet/fsharp/pull/16262
-    >
+    > Information about the release notes entries format can be found in the [documentation](https://fsharp.github.io/fsharp-compiler-docs/release-notes/About.html).
+    > Example:
+    > * More inlines for Result module. ([PR #16106](https://github.com/dotnet/fsharp/pull/16106))
+    > * Correctly handle assembly imports with public key token of 0 length. ([Issue #16359](https://github.com/dotnet/fsharp/issues/16359), [PR #16363](https://github.com/dotnet/fsharp/pull/16363))
+    > *`while!` ([Language suggestion #1038](https://github.com/fsharp/fslang-suggestions/issues/1038), [PR #14238](https://github.com/dotnet/fsharp/pull/14238))
 
     > **If you believe that release notes are not necessary for this PR, please add `NO_RELEASE_NOTES` label to the pull request.**
\ No newline at end of file
diff --git a/.github/workflows/check_release_notes.yml b/.github/workflows/check_release_notes.yml
index 14b3c85ca51..359046abcde 100644
--- a/.github/workflows/check_release_notes.yml
+++ b/.github/workflows/check_release_notes.yml
@@ -1,6 +1,6 @@
 name: Check release notes
 on:
-  pull_request:
+  pull_request_target:
     types: [opened, synchronize, reopened, labeled, unlabeled]
     branches:
         - 'main'
@@ -85,10 +85,10 @@ jobs:
         [[ "$VISUAL_STUDIO_VERSION" =~ ^[0-9]+\.[0-9]+$ ]] || (echo "   Invalid Visual Studio Version parsed"; exit 1)
 
         _release_notes_base_path='docs/release-notes'
-        _fsharp_core_release_notes_path="${_release_notes_base_path}/FSharp.Core/${FSHARP_CORE_VERSION}.md"
-        _fsharp_compiler_release_notes_path="${_release_notes_base_path}/FSharp.Compiler.Service/${FSHARP_CORE_VERSION}.md"
-        _fsharp_language_release_notes_path="${_release_notes_base_path}/Language/preview.md"
-        _fsharp_vs_release_notes_path="${_release_notes_base_path}/VisualStudio/${VISUAL_STUDIO_VERSION}.md"
+        _fsharp_core_release_notes_path="${_release_notes_base_path}/.FSharp.Core/${FSHARP_CORE_VERSION}.md"
+        _fsharp_compiler_release_notes_path="${_release_notes_base_path}/.FSharp.Compiler.Service/${FSHARP_CORE_VERSION}.md"
+        _fsharp_language_release_notes_path="${_release_notes_base_path}/.Language/preview.md"
+        _fsharp_vs_release_notes_path="${_release_notes_base_path}/.VisualStudio/${VISUAL_STUDIO_VERSION}.md"
 
         readonly paths=(
             "src/FSharp.Core|${_fsharp_core_release_notes_path}"
@@ -133,19 +133,19 @@ jobs:
 
                     if [[ ${_pr_link_occurences} -eq 1 ]]; then
                         echo "                  Found pull request URL in $release_notes once"
-                        RELEASE_NOTES_FOUND+="> | \\\`$path\\\` | [$release_notes](${FSHARP_REPO_URL}/$release_notes) | |"
+                        RELEASE_NOTES_FOUND+="> | \\\`$path\\\` | [$release_notes](${FSHARP_REPO_URL}/tree/main/$release_notes) | |"
                         RELEASE_NOTES_FOUND+=$'\n'
                     elif [[ ${_pr_link_occurences} -eq 0 ]]; then
                         echo "                  Did not find pull request URL in $release_notes"
                         DESCRIPTION="**No current pull request URL (${PR_URL}) found, please consider adding it**"
-                        RELEASE_NOTES_FOUND+="> | \\\`$path\\\` | [$release_notes](${FSHARP_REPO_URL}/$release_notes) | ${DESCRIPTION} |"
+                        RELEASE_NOTES_FOUND+="> | \\\`$path\\\` | [$release_notes](${FSHARP_REPO_URL}/tree/main/$release_notes) | ${DESCRIPTION} |"
                         RELEASE_NOTES_FOUND+=$'\n'
                         PULL_REQUEST_FOUND=false
                     fi
                 else
                     echo "          Did not find $release_notes in modified files"
                     DESCRIPTION="**No release notes found or release notes format is not correct**"
-                    RELEASE_NOTES_NOT_FOUND+="| \\\`$path\\\` | [$release_notes](${FSHARP_REPO_URL}/$release_notes) | ${DESCRIPTION} |"
+                    RELEASE_NOTES_NOT_FOUND+="| \\\`$path\\\` | [$release_notes](${FSHARP_REPO_URL}/tree/main/$release_notes) | ${DESCRIPTION} |"
                     RELEASE_NOTES_NOT_FOUND+=$'\n'
                 fi
             else
@@ -161,24 +161,29 @@ jobs:
             RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
             RELEASE_NOTES_MESSAGE_DETAILS+=$"> [!CAUTION]"
             RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
-            RELEASE_NOTES_MESSAGE_DETAILS+=$"> **No release notes found for the following paths.**"
+            RELEASE_NOTES_MESSAGE_DETAILS+=$"> **No release notes found for the changed paths (see table below).**"
             RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
             RELEASE_NOTES_MESSAGE_DETAILS+=$">"
             RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
-            RELEASE_NOTES_MESSAGE_DETAILS+=$"> Please make sure to add an entry with short succint description of the change as well as link to this pull request."
+            RELEASE_NOTES_MESSAGE_DETAILS+=$"> Please make sure to add an entry with an informative description of the change as well as link to this pull request, issue and language suggestion if applicable. Release notes for this repository are based on [Keep A Changelog](https://keepachangelog.com/en/1.1.0/) format."
             RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
             RELEASE_NOTES_MESSAGE_DETAILS+=$">"
             RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
-            RELEASE_NOTES_MESSAGE_DETAILS+=$"> Examples: "
+            RELEASE_NOTES_MESSAGE_DETAILS+=$"> **The following format is recommended for this repository:**"
             RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
-            RELEASE_NOTES_MESSAGE_DETAILS+=$"> \\\`- Respect line limit in quick info popup - https://github.com/dotnet/fsharp/pull/16208\\\`"
+            RELEASE_NOTES_MESSAGE_DETAILS+=$">"
+            RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
+            RELEASE_NOTES_MESSAGE_DETAILS+=$">"
             RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
-            RELEASE_NOTES_MESSAGE_DETAILS+=$"> \\\`- More inlines for Result module - https://github.com/dotnet/fsharp/pull/16106\\\`"
+            RELEASE_NOTES_MESSAGE_DETAILS+=$"> \\\`* . ([PR #XXXXX](https://github.com/dotnet/fsharp/pull/XXXXX))\\\`"
             RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
-            RELEASE_NOTES_MESSAGE_DETAILS+=$"> \\\`- Miscellaneous fixes to parens analysis - https://github.com/dotnet/fsharp/pull/16262\\\`"
+            RELEASE_NOTES_MESSAGE_DETAILS+=$">"
+            RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
+            RELEASE_NOTES_MESSAGE_DETAILS+=$">"
+            RELEASE_NOTES_MESSAGE_DETAILS+=$"> See examples in the files, listed in the table below or in th full documentation at https://fsharp.github.io/fsharp-compiler-docs/release-notes/About.html."
             RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
             RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
-            RELEASE_NOTES_MESSAGE_DETAILS+=$'**If you believe that release notes are not necessary for this PR, please add "NO_RELEASE_NOTES" label to the pull request.**'
+            RELEASE_NOTES_MESSAGE_DETAILS+=$'**If you believe that release notes are not necessary for this PR, please add NO_RELEASE_NOTES label to the pull request.**'
             RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
             RELEASE_NOTES_MESSAGE_DETAILS+=$'\n'
             RELEASE_NOTES_MESSAGE_DETAILS+=$"**You can open this PR in browser to add release notes: [open in github.dev](https://github.dev/dotnet/fsharp/pull/${PR_NUMBER})**"
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 965a1b47fc3..1c0af1d324e 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -6,7 +6,7 @@
             "id": "fscArgsPrompt",
             "description": "Enter arguments for fsc",
             "default": "",
-            "type": "promptString",
+            "type": "promptString"
         },
         {
             "id": "fsiArgsPrompt",
@@ -17,17 +17,17 @@
     ],
     "configurations": [
         {
-            "name": "Launch FSI (Debug, .NET 7.0)",
+            "name": "Launch FSI (Debug)",
             "type": "coreclr",
             "request": "launch",
             // TODO: Shall we assume that it's already been built, or build it every time we debug?
-            "preLaunchTask": "Build (Debug)",
+            "preLaunchTask": "${defaultBuildTask}",
             // If you have changed target frameworks, make sure to update the program p
             "program": "${workspaceFolder}/artifacts/bin/fsi/Debug/net8.0/fsi.dll",
             "args": [
                 "${input:fsiArgsPrompt}"
             ],
-            "cwd": "${workspaceFolder}/src",
+            "cwd": "${workspaceFolder}",
             "console": "integratedTerminal", // This is the default to be able to run in Codespaces.
             "internalConsoleOptions": "neverOpen",
             "suppressJITOptimizations": true,
@@ -44,16 +44,19 @@
                     "enabled": true
                 }
             },
+            "allowFastEvaluate": true
         },
         {
-            "name": "Launch FSC (Debug, .NET 7.0)",
+            "name": "Launch FSC (Debug)",
             "type": "coreclr",
             "request": "launch",
             // TODO: Shall we assume that it's already been built, or build it every time we debug?
-            "preLaunchTask": "Build (Debug)",
+            "preLaunchTask": "${defaultBuildTask}",
             // If you have changed target frameworks, make sure to update the program path.
             "program": "${workspaceFolder}/artifacts/bin/fsc/Debug/net8.0/fsc.dll",
             "args": [
+                "--targetprofile:netstandard",
+                "--simpleresolution",
                 "${input:fscArgsPrompt}"
             ],
             "cwd": "${workspaceFolder}",
@@ -73,9 +76,10 @@
                     "enabled": true
                 }
             },
+            "allowFastEvaluate": true
         },
         {
-            "name": "Attach to a .NET process",
+            "name": "Attach to a .NET process with debugger",
             "type": "coreclr",
             "request": "attach",
             "processId": "${command:pickProcess}",
@@ -86,7 +90,8 @@
             },
             "justMyCode": true,
             "enableStepFiltering": false,
-            "requireExactSource": false
+            "requireExactSource": false,
+            "allowFastEvaluate": true
         }
     ]
 }
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 1728f4efc97..c80b85f366a 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -2,6 +2,25 @@
     // See https://go.microsoft.com/fwlink/?LinkId=733558
     // for the documentation about the tasks.json format
     "version": "2.0.0",
+    "inputs": [
+        {
+            "id": "fscArgsPrompt",
+            "description": "Enter arguments for fsc",
+            "default": "",
+            "type": "promptString",
+        },
+        {
+            "id": "fsiArgsPrompt",
+            "description": "Enter arguments for fsi",
+            "default": "",
+            "type": "promptString",
+        },
+        {
+            "id": "PickProcess",
+            "description": "Enter process id",
+            "type": "promptString"
+        }
+    ],
     "windows": {
         "options": {
             "shell": {
@@ -71,18 +90,98 @@
             "problemMatcher": "$msCompile",
             "group": "build"
         },
+        {
+            "label": "Run FSI with dotnet-trace",
+            "command": "dotnet",
+            "type": "shell",
+            "args": [
+                "dotnet-trace",
+                "collect",
+                "--format",
+                "Speedscope",
+                "--",
+                "dotnet",
+                "${workspaceFolder}/artifacts/bin/fsi/Debug/net8.0/fsi.dll",
+                "${input:fsiArgsPrompt}"
+            ],
+            "problemMatcher": "$msCompile",
+            "group": "none"
+        },
+        {
+            "label": "Run FSC with dotnet-trace",
+            "command": "dotnet",
+            "type": "shell",
+            "args": [
+                "dotnet-trace",
+                "collect",
+                "--format",
+                "Speedscope",
+                "--",
+                "dotnet",
+                "${workspaceFolder}/artifacts/bin/fsc/Debug/net8.0/fsc.dll",
+                "--targetprofile:netstandard",
+                "--simpleresolution",
+                "${input:fscArgsPrompt}"
+            ],
+            "problemMatcher": "$msCompile",
+            "group": "none"
+        },
+        {
+            "label": "Create a process dump with dotnet-dump",
+            "command": "dotnet",
+            "type": "shell",
+            "args": [
+                "dotnet-dump",
+                "collect",
+                "--diag",
+                "--crashreport",
+                "--type",
+                "Full",
+                "--process-id",
+                "${input:PickProcess}",
+            ],
+            "problemMatcher": "$msCompile",
+            "group": "none"
+        },
+        {
+            "label": "Create a process GC dump with dotnet-gcdump",
+            "command": "dotnet",
+            "type": "shell",
+            "args": [
+                "dotnet-gcdump",
+                "collect",
+                "--process-id",
+                "${input:PickProcess}",
+            ],
+            "problemMatcher": "$msCompile",
+            "group": "none"
+        },
+        {
+            "label": "Collect process counters with dotnet-counters",
+            "command": "dotnet",
+            "type": "shell",
+            "args": [
+                "dotnet-counters",
+                "collect",
+                "--process-id",
+                "${input:PickProcess}",
+            ],
+            "problemMatcher": "$msCompile",
+            "group": "none"
+        },
         {
             "label": "Update xlf files",
-            "command": "./build.sh",
+            "command": "dotnet",
+            "type": "shell",
+            "args": ["build", "-t:UpdateXlf", "src/Compiler/FSharp.Compiler.Service.fsproj"],
+            "problemMatcher": "$msCompile",
+            "group": "build"
+        },
+        {
+            "label": "Run Fantomas",
+            "command": "dotnet",
+            "args": ["fantomas", "."],
             "type": "shell",
-            "windows": {
-                "command": "${workspaceFolder}/Build.cmd"
-            },
-            "options": {
-                "env": {
-                    "UpdateXlfOnBuild": "true"
-                }
-            },
             "problemMatcher": "$msCompile",
             "group": "build"
         }
diff --git a/BenchmarkDotNet.Artifacts/results/TaskPerf.Benchmarks-report-github.md b/BenchmarkDotNet.Artifacts/results/TaskPerf.Benchmarks-report-github.md
deleted file mode 100644
index 6cce7d6b240..00000000000
--- a/BenchmarkDotNet.Artifacts/results/TaskPerf.Benchmarks-report-github.md
+++ /dev/null
@@ -1,67 +0,0 @@
-``` ini
-
-BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042
-Intel Xeon CPU E5-1620 0 3.60GHz, 1 CPU, 8 logical and 4 physical cores
-.NET Core SDK=5.0.104
-  [Host]     : .NET Core 5.0.6 (CoreCLR 5.0.621.22011, CoreFX 5.0.621.22011), X64 RyuJIT DEBUG
-  DefaultJob : .NET Core 5.0.6 (CoreCLR 5.0.621.22011, CoreFX 5.0.621.22011), X64 RyuJIT
-
-
-```
-|                                      Method |             Categories |           Mean |         Error |        StdDev |         Median |  Ratio | RatioSD |      Gen 0 |   Gen 1 | Gen 2 |   Allocated |
-|-------------------------------------------- |----------------------- |---------------:|--------------:|--------------:|---------------:|-------:|--------:|-----------:|--------:|------:|------------:|
-|                   ManyWriteFile_CSharpTasks |          ManyWriteFile |     4,186.6 μs |      81.32 μs |     201.00 μs |     4,187.4 μs |   1.00 |    0.00 |    15.6250 |       - |     - |    117288 B |
-|                   ManyWriteFile_taskBuilder |          ManyWriteFile |     5,744.5 μs |     124.34 μs |     356.76 μs |     5,712.3 μs |   1.38 |    0.11 |    62.5000 |       - |     - |    444882 B |
-|                         ManyWriteFile_async |          ManyWriteFile |     6,108.8 μs |     121.27 μs |     271.23 μs |     6,132.1 μs |   1.46 |    0.10 |   132.8125 |       - |     - |    704991 B |
-|                          ManyWriteFile_task |          ManyWriteFile |     5,014.3 μs |     100.18 μs |     204.65 μs |     4,973.0 μs |   1.19 |    0.07 |    15.6250 |       - |     - |    116996 B |
-|                        ManyWriteFile_async2 |          ManyWriteFile |     5,358.4 μs |     106.05 μs |     211.79 μs |     5,374.1 μs |   1.27 |    0.07 |    15.6250 |       - |     - |    117140 B |
-|                                             |                        |                |               |               |                |        |         |            |         |       |             |
-|                   NonAsyncBinds_CSharpTasks |          NonAsyncBinds |    17,444.8 μs |     374.32 μs |   1,097.80 μs |    17,030.4 μs |   1.00 |    0.00 | 15125.0000 |       - |     - |  79200000 B |
-|                   NonAsyncBinds_taskBuilder |          NonAsyncBinds |    26,000.1 μs |     440.68 μs |     880.09 μs |    25,621.3 μs |   1.47 |    0.09 | 22187.5000 |       - |     - | 116000000 B |
-|                         NonAsyncBinds_async |          NonAsyncBinds | 1,303,920.2 μs |  63,453.67 μs | 177,930.90 μs | 1,269,891.9 μs |  74.52 |   10.59 | 52000.0000 |       - |     - | 276000000 B |
-|                        NonAsyncBinds_async2 |          NonAsyncBinds |    24,213.0 μs |     191.23 μs |     178.88 μs |    24,168.6 μs |   1.38 |    0.09 | 18812.5000 | 62.5000 |     - |  98400000 B |
-|                          NonAsyncBinds_task |          NonAsyncBinds |    16,693.5 μs |     302.84 μs |     759.75 μs |    16,586.1 μs |   0.95 |    0.07 | 15125.0000 |       - |     - |  79200000 B |
-|                                             |                        |                |               |               |                |        |         |            |         |       |             |
-|                      AsyncBinds_CSharpTasks |             AsyncBinds |     8,335.4 μs |     190.47 μs |     558.61 μs |     8,197.5 μs |   1.00 |    0.00 |    15.6250 |       - |     - |    112119 B |
-|                      AsyncBinds_taskBuilder |             AsyncBinds |    11,567.6 μs |     229.28 μs |     522.18 μs |    11,360.0 μs |   1.39 |    0.12 |   296.8750 |       - |     - |   1559252 B |
-|                            AsyncBinds_async |             AsyncBinds |   127,872.2 μs |   3,090.27 μs |   8,866.56 μs |   127,900.8 μs |  15.38 |    1.47 |  1333.3333 |       - |     - |   8312000 B |
-|                             AsyncBinds_task |             AsyncBinds |     9,897.9 μs |     314.55 μs |     927.46 μs |    10,058.4 μs |   1.19 |    0.15 |    31.2500 |       - |     - |    192096 B |
-|                           AsyncBinds_async2 |             AsyncBinds |     8,165.2 μs |     156.64 μs |     347.09 μs |     8,051.9 μs |   0.98 |    0.07 |    62.5000 |       - |     - |    352218 B |
-|                                             |                        |                |               |               |                |        |         |            |         |       |             |
-|                  SingleSyncTask_CSharpTasks |         SingleSyncTask |     8,668.5 μs |     170.65 μs |     233.59 μs |     8,595.4 μs |   1.00 |    0.00 |          - |       - |     - |           - |
-|                  SingleSyncTask_taskBuilder |         SingleSyncTask |    12,402.4 μs |     103.89 μs |      92.10 μs |    12,366.7 μs |   1.43 |    0.04 |  9171.8750 |       - |     - |  48000000 B |
-|                        SingleSyncTask_async |         SingleSyncTask | 3,659,569.1 μs | 109,062.88 μs | 298,557.86 μs | 3,576,228.4 μs | 409.11 |   38.68 | 91000.0000 |       - |     - | 475999216 B |
-|                         SingleSyncTask_task |         SingleSyncTask |    10,642.1 μs |      90.05 μs |      84.23 μs |    10,622.2 μs |   1.23 |    0.04 |          - |       - |     - |           - |
-|                       SingleSyncTask_async2 |         SingleSyncTask |    28,177.5 μs |     263.90 μs |     220.37 μs |    28,134.6 μs |   3.25 |    0.08 |  7625.0000 |       - |     - |  40000000 B |
-|                                             |                        |                |               |               |                |        |         |            |         |       |             |
-|                  SyncBuilderLoop_NormalCode |                   sync |    81,206.3 μs |   1,598.95 μs |   1,570.38 μs |    80,813.7 μs |   1.00 |    0.00 | 36714.2857 |       - |     - | 192176000 B |
-|                SyncBuilderLoop_WorkflowCode |                   sync |    81,811.3 μs |   1,610.38 μs |   3,140.93 μs |    80,621.9 μs |   1.02 |    0.05 | 36714.2857 |       - |     - | 192176000 B |
-|                                             |                        |                |               |               |                |        |         |            |         |       |             |
-|               TinyVariableSizedList_Builtin |  TinyVariableSizedList |    57,762.3 μs |   1,721.40 μs |   4,827.00 μs |    56,313.5 μs |   1.00 |    0.00 | 20375.0000 |       - |     - | 106666656 B |
-|            TinyVariableSizedList_NewBuilder |  TinyVariableSizedList |    17,122.1 μs |     341.76 μs |     650.23 μs |    17,233.0 μs |   0.29 |    0.03 |  2031.2500 |       - |     - |  10666656 B |
-|                                             |                        |                |               |               |                |        |         |            |         |       |             |
-|                   VariableSizedList_Builtin |      VariableSizedList |   330,273.8 μs |   6,534.98 μs |  13,051.05 μs |   328,659.3 μs |   1.00 |    0.00 | 63000.0000 |       - |     - | 330666624 B |
-|                VariableSizedList_NewBuilder |      VariableSizedList |   167,451.6 μs |   2,840.89 μs |   2,217.98 μs |   167,326.7 μs |   0.51 |    0.02 | 44750.0000 |       - |     - | 234666934 B |
-|                                             |                        |                |               |               |                |        |         |            |         |       |             |
-|                       FixedSizeList_Builtin |         FixedSizedList |   100,128.5 μs |   1,968.29 μs |   3,885.21 μs |   100,084.8 μs |   1.00 |    0.00 | 61166.6667 |       - |     - | 320000000 B |
-|                    FixedSizeList_NewBuilder |         FixedSizedList |   229,639.0 μs |   4,589.37 μs |  11,846.63 μs |   227,278.1 μs |   2.30 |    0.13 | 61000.0000 |       - |     - | 320000000 B |
-|                                             |                        |                |               |               |                |        |         |            |         |       |             |
-|              TinyVariableSizedArray_Builtin | TinyVariableSizedArray |   100,414.3 μs |   1,995.07 μs |   4,462.26 μs |   100,631.3 μs |   1.00 |    0.00 | 30000.0000 |       - |     - | 157333304 B |
-|           TinyVariableSizedArray_NewBuilder | TinyVariableSizedArray |    28,538.5 μs |     632.86 μs |   1,825.93 μs |    28,426.7 μs |   0.29 |    0.02 | 10687.5000 |       - |     - |  55999968 B |
-|                                             |                        |                |               |               |                |        |         |            |         |       |             |
-|                  VariableSizedArray_Builtin |     VariableSizedArray |   356,489.5 μs |   3,061.89 μs |   2,714.29 μs |   356,174.5 μs |   1.00 |    0.00 | 77000.0000 |       - |     - | 405333840 B |
-|               VariableSizedArray_NewBuilder |     VariableSizedArray |   161,909.3 μs |     861.02 μs |     672.23 μs |   161,860.8 μs |   0.45 |    0.00 | 59000.0000 |       - |     - | 309333476 B |
-|                                             |                        |                |               |               |                |        |         |            |         |       |             |
-|                      FixedSizeArray_Builtin |        FixedSizedArray |    32,944.8 μs |     777.85 μs |   2,293.52 μs |    32,391.8 μs |   1.00 |    0.00 | 19875.0000 |       - |     - | 104000000 B |
-|                   FixedSizeArray_NewBuilder |        FixedSizedArray |   219,352.6 μs |   4,288.40 μs |  10,837.34 μs |   217,830.4 μs |   6.65 |    0.60 | 82333.3333 |       - |     - | 432000000 B |
-|                                             |                        |                |               |               |                |        |         |            |         |       |             |
-|                  MultiStepOption_OldBuilder |        MultiStepOption |    63,360.5 μs |   1,199.04 μs |   1,062.92 μs |    63,133.5 μs |   1.00 |    0.00 | 38750.0000 |       - |     - | 202666703 B |
-|                  MultiStepOption_NewBuilder |        MultiStepOption |    20,179.8 μs |     622.44 μs |   1,775.86 μs |    19,705.5 μs |   0.29 |    0.02 | 13437.5000 |       - |     - |  70399968 B |
-|                   MultiStepOption_NoBuilder |        MultiStepOption |    19,727.8 μs |     469.72 μs |   1,362.75 μs |    19,395.3 μs |   0.32 |    0.02 | 13437.5000 |       - |     - |  70399968 B |
-|                                             |                        |                |               |               |                |        |         |            |         |       |             |
-|             MultiStepValueOption_OldBuilder |   MultiStepValueOption |    47,237.3 μs |     909.93 μs |     759.83 μs |    47,211.0 μs |   1.00 |    0.00 | 19090.9091 |       - |     - | 100266664 B |
-|             MultiStepValueOption_NewBuilder |   MultiStepValueOption |     4,144.6 μs |      46.31 μs |      43.32 μs |     4,146.1 μs |   0.09 |    0.00 |          - |       - |     - |           - |
-|              MultiStepValueOption_NoBuilder |   MultiStepValueOption |     3,824.0 μs |      75.26 μs |      73.92 μs |     3,806.3 μs |   0.08 |    0.00 |          - |       - |     - |           - |
-|                                             |                        |                |               |               |                |        |         |            |         |       |             |
-| NestedForLoops_taskSeqUsingRawResumableCode |                taskSeq |       983.7 μs |      18.23 μs |      17.90 μs |       984.7 μs |   1.61 |    0.04 |    54.6875 |       - |     - |    295641 B |
-|        NestedForLoops_CSharpAsyncEnumerable |                taskSeq |       612.9 μs |      10.04 μs |       8.90 μs |       615.5 μs |   1.00 |    0.00 |    24.4141 |       - |     - |    131280 B |
diff --git a/Directory.Build.props b/Directory.Build.props
index 879bd89410f..10c53909035 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -16,6 +16,10 @@
       true
   
 
+  
+      true
+  
+
   
   
       true
diff --git a/Directory.Build.targets b/Directory.Build.targets
index 5952e0ed670..079e0e68fd4 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -13,7 +13,4 @@
     
     
   
- 
-      
- 
 
diff --git a/FSharp.Benchmarks.sln b/FSharp.Benchmarks.sln
new file mode 100644
index 00000000000..2ace22c1515
--- /dev/null
+++ b/FSharp.Benchmarks.sln
@@ -0,0 +1,119 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32113.165
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MicroPerfCSharp", "tests\benchmarks\CompiledCodeBenchmarks\MicroPerf\CS\MicroPerfCSharp.csproj", "{CA98804B-E371-45AB-814F-AC4996579B6F}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Service", "src\Compiler\FSharp.Compiler.Service.fsproj", "{9B4528F6-8883-475C-AAF0-4F646233D30A}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Core", "src\FSharp.Core\FSharp.Core.fsproj", "{ADB51E6C-2D63-4AB1-9F2C-8E869FEFD170}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.DependencyManager.Nuget", "src\FSharp.DependencyManager.Nuget\FSharp.DependencyManager.Nuget.fsproj", "{9B98A267-BE47-4711-A1B6-98F3F321E3DD}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "MicroPerf", "tests\benchmarks\CompiledCodeBenchmarks\MicroPerf\MicroPerf.fsproj", "{ED766F38-BD2B-436B-AF73-7BE6FAE061DD}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TaskPerf", "tests\benchmarks\CompiledCodeBenchmarks\TaskPerf\TaskPerf\TaskPerf.fsproj", "{4779C245-9B85-4491-85EB-B0AF6D818E81}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TaskPerfCSharp", "tests\benchmarks\CompiledCodeBenchmarks\TaskPerf\TaskPerfCSharp\TaskPerfCSharp.csproj", "{38CAA9B6-E4B8-42CB-B4E3-C2DC7D481913}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "HistoricalBenchmark", "tests\benchmarks\FCSBenchmarks\BenchmarkComparison\HistoricalBenchmark.fsproj", "{66E23120-5E94-49AE-A263-24583007F5F5}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "HistoricalBenchmark.Runner", "tests\benchmarks\FCSBenchmarks\BenchmarkComparison\HistoricalBenchmark.Runner\HistoricalBenchmark.Runner.fsproj", "{2A1289B1-1539-48CB-BE03-807FE4BC0387}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Benchmarks", "tests\benchmarks\FCSBenchmarks\CompilerServiceBenchmarks\FSharp.Compiler.Benchmarks.fsproj", "{50D1ECF3-DF38-4A8E-AC3B-2AF1E63263B8}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FCSSourceFiles", "tests\benchmarks\FCSBenchmarks\FCSSourceFiles\FCSSourceFiles.fsproj", "{0E2A7B27-3AD3-4C1D-BA0D-008A1200946F}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Test.Utilities", "tests\FSharp.Test.Utilities\FSharp.Test.Utilities.fsproj", "{0B149238-0912-493E-8877-F831AE01B942}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+		ReleaseCompressed|Any CPU = ReleaseCompressed|Any CPU
+		Proto|Any CPU = Proto|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CA98804B-E371-45AB-814F-AC4996579B6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CA98804B-E371-45AB-814F-AC4996579B6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CA98804B-E371-45AB-814F-AC4996579B6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CA98804B-E371-45AB-814F-AC4996579B6F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CA98804B-E371-45AB-814F-AC4996579B6F}.ReleaseCompressed|Any CPU.ActiveCfg = Debug|Any CPU
+		{CA98804B-E371-45AB-814F-AC4996579B6F}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
+		{9B4528F6-8883-475C-AAF0-4F646233D30A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9B4528F6-8883-475C-AAF0-4F646233D30A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9B4528F6-8883-475C-AAF0-4F646233D30A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9B4528F6-8883-475C-AAF0-4F646233D30A}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9B4528F6-8883-475C-AAF0-4F646233D30A}.ReleaseCompressed|Any CPU.ActiveCfg = ReleaseCompressed|Any CPU
+		{9B4528F6-8883-475C-AAF0-4F646233D30A}.ReleaseCompressed|Any CPU.Build.0 = ReleaseCompressed|Any CPU
+		{9B4528F6-8883-475C-AAF0-4F646233D30A}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
+		{ADB51E6C-2D63-4AB1-9F2C-8E869FEFD170}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{ADB51E6C-2D63-4AB1-9F2C-8E869FEFD170}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{ADB51E6C-2D63-4AB1-9F2C-8E869FEFD170}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{ADB51E6C-2D63-4AB1-9F2C-8E869FEFD170}.Release|Any CPU.Build.0 = Release|Any CPU
+		{ADB51E6C-2D63-4AB1-9F2C-8E869FEFD170}.ReleaseCompressed|Any CPU.ActiveCfg = ReleaseCompressed|Any CPU
+		{ADB51E6C-2D63-4AB1-9F2C-8E869FEFD170}.ReleaseCompressed|Any CPU.Build.0 = ReleaseCompressed|Any CPU
+		{ADB51E6C-2D63-4AB1-9F2C-8E869FEFD170}.Proto|Any CPU.ActiveCfg = Proto|Any CPU
+		{ADB51E6C-2D63-4AB1-9F2C-8E869FEFD170}.Proto|Any CPU.Build.0 = Proto|Any CPU
+		{9B98A267-BE47-4711-A1B6-98F3F321E3DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9B98A267-BE47-4711-A1B6-98F3F321E3DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9B98A267-BE47-4711-A1B6-98F3F321E3DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9B98A267-BE47-4711-A1B6-98F3F321E3DD}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9B98A267-BE47-4711-A1B6-98F3F321E3DD}.ReleaseCompressed|Any CPU.ActiveCfg = ReleaseCompressed|Any CPU
+		{9B98A267-BE47-4711-A1B6-98F3F321E3DD}.ReleaseCompressed|Any CPU.Build.0 = ReleaseCompressed|Any CPU
+		{9B98A267-BE47-4711-A1B6-98F3F321E3DD}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
+		{ED766F38-BD2B-436B-AF73-7BE6FAE061DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{ED766F38-BD2B-436B-AF73-7BE6FAE061DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{ED766F38-BD2B-436B-AF73-7BE6FAE061DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{ED766F38-BD2B-436B-AF73-7BE6FAE061DD}.Release|Any CPU.Build.0 = Release|Any CPU
+		{ED766F38-BD2B-436B-AF73-7BE6FAE061DD}.ReleaseCompressed|Any CPU.ActiveCfg = Debug|Any CPU
+		{ED766F38-BD2B-436B-AF73-7BE6FAE061DD}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
+		{4779C245-9B85-4491-85EB-B0AF6D818E81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{4779C245-9B85-4491-85EB-B0AF6D818E81}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{4779C245-9B85-4491-85EB-B0AF6D818E81}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{4779C245-9B85-4491-85EB-B0AF6D818E81}.Release|Any CPU.Build.0 = Release|Any CPU
+		{4779C245-9B85-4491-85EB-B0AF6D818E81}.ReleaseCompressed|Any CPU.ActiveCfg = Debug|Any CPU
+		{4779C245-9B85-4491-85EB-B0AF6D818E81}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
+		{38CAA9B6-E4B8-42CB-B4E3-C2DC7D481913}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{38CAA9B6-E4B8-42CB-B4E3-C2DC7D481913}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{38CAA9B6-E4B8-42CB-B4E3-C2DC7D481913}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{38CAA9B6-E4B8-42CB-B4E3-C2DC7D481913}.Release|Any CPU.Build.0 = Release|Any CPU
+		{38CAA9B6-E4B8-42CB-B4E3-C2DC7D481913}.ReleaseCompressed|Any CPU.ActiveCfg = Debug|Any CPU
+		{38CAA9B6-E4B8-42CB-B4E3-C2DC7D481913}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
+		{66E23120-5E94-49AE-A263-24583007F5F5}.Debug|Any CPU.ActiveCfg = Release|Any CPU
+		{66E23120-5E94-49AE-A263-24583007F5F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{66E23120-5E94-49AE-A263-24583007F5F5}.Release|Any CPU.Build.0 = Release|Any CPU
+		{66E23120-5E94-49AE-A263-24583007F5F5}.ReleaseCompressed|Any CPU.ActiveCfg = Release|Any CPU
+		{66E23120-5E94-49AE-A263-24583007F5F5}.Proto|Any CPU.ActiveCfg = Release|Any CPU
+		{2A1289B1-1539-48CB-BE03-807FE4BC0387}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{2A1289B1-1539-48CB-BE03-807FE4BC0387}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2A1289B1-1539-48CB-BE03-807FE4BC0387}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{2A1289B1-1539-48CB-BE03-807FE4BC0387}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2A1289B1-1539-48CB-BE03-807FE4BC0387}.ReleaseCompressed|Any CPU.ActiveCfg = Debug|Any CPU
+		{2A1289B1-1539-48CB-BE03-807FE4BC0387}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
+		{50D1ECF3-DF38-4A8E-AC3B-2AF1E63263B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{50D1ECF3-DF38-4A8E-AC3B-2AF1E63263B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{50D1ECF3-DF38-4A8E-AC3B-2AF1E63263B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{50D1ECF3-DF38-4A8E-AC3B-2AF1E63263B8}.Release|Any CPU.Build.0 = Release|Any CPU
+		{50D1ECF3-DF38-4A8E-AC3B-2AF1E63263B8}.ReleaseCompressed|Any CPU.ActiveCfg = Debug|Any CPU
+		{50D1ECF3-DF38-4A8E-AC3B-2AF1E63263B8}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
+		{0E2A7B27-3AD3-4C1D-BA0D-008A1200946F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0E2A7B27-3AD3-4C1D-BA0D-008A1200946F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0E2A7B27-3AD3-4C1D-BA0D-008A1200946F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{0E2A7B27-3AD3-4C1D-BA0D-008A1200946F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{0E2A7B27-3AD3-4C1D-BA0D-008A1200946F}.ReleaseCompressed|Any CPU.ActiveCfg = Debug|Any CPU
+		{0E2A7B27-3AD3-4C1D-BA0D-008A1200946F}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
+		{0B149238-0912-493E-8877-F831AE01B942}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0B149238-0912-493E-8877-F831AE01B942}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0B149238-0912-493E-8877-F831AE01B942}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{0B149238-0912-493E-8877-F831AE01B942}.Release|Any CPU.Build.0 = Release|Any CPU
+		{0B149238-0912-493E-8877-F831AE01B942}.ReleaseCompressed|Any CPU.ActiveCfg = Debug|Any CPU
+		{0B149238-0912-493E-8877-F831AE01B942}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {6D8EE73F-B214-462F-8774-84EF625EA6E4}
+	EndGlobalSection
+EndGlobal
diff --git a/VisualFSharp.sln b/VisualFSharp.sln
index 94d3cef1d10..bedba19a485 100644
--- a/VisualFSharp.sln
+++ b/VisualFSharp.sln
@@ -189,8 +189,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FCSBenchmarks", "FCSBenchma
 		tests\benchmarks\FCSBenchmarks\SmokeTestAllBenchmarks.ps1 = tests\benchmarks\FCSBenchmarks\SmokeTestAllBenchmarks.ps1
 	EndProjectSection
 EndProject
-Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fsharp.ProfilingStartpointProject", "tests\benchmarks\Fsharp.ProfilingStartpointProject\Fsharp.ProfilingStartpointProject.fsproj", "{FE23BB65-276A-4E41-8CC7-F7752241DEBA}"
-EndProject
 Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Editor.Tests", "vsintegration\tests\FSharp.Editor.Tests\FSharp.Editor.Tests.fsproj", "{CBC96CC7-65AB-46EA-A82E-F6A788DABF80}"
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FSharp.Editor.IntegrationTests", "vsintegration\tests\FSharp.Editor.IntegrationTests\FSharp.Editor.IntegrationTests.csproj", "{E31F9B59-FCF1-4D04-8762-C7BB60285A7B}"
@@ -999,18 +997,6 @@ Global
 		{583182E1-3484-4A8F-AC06-7C0D232C0CA4}.Release|Any CPU.Build.0 = Release|Any CPU
 		{583182E1-3484-4A8F-AC06-7C0D232C0CA4}.Release|x86.ActiveCfg = Release|Any CPU
 		{583182E1-3484-4A8F-AC06-7C0D232C0CA4}.Release|x86.Build.0 = Release|Any CPU
-		{FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Debug|x86.Build.0 = Debug|Any CPU
-		{FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
-		{FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Proto|Any CPU.Build.0 = Debug|Any CPU
-		{FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Proto|x86.ActiveCfg = Debug|Any CPU
-		{FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Proto|x86.Build.0 = Debug|Any CPU
-		{FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Release|Any CPU.Build.0 = Release|Any CPU
-		{FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Release|x86.ActiveCfg = Release|Any CPU
-		{FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Release|x86.Build.0 = Release|Any CPU
 		{CBC96CC7-65AB-46EA-A82E-F6A788DABF80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{CBC96CC7-65AB-46EA-A82E-F6A788DABF80}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{CBC96CC7-65AB-46EA-A82E-F6A788DABF80}.Debug|x86.ActiveCfg = Debug|Any CPU
@@ -1125,7 +1111,6 @@ Global
 		{EB015235-1E07-4CDA-9CC6-3FBCC27910D1} = {B8DDA694-7939-42E3-95E5-265C2217C142}
 		{583182E1-3484-4A8F-AC06-7C0D232C0CA4} = {39CDF34B-FB23-49AE-AB27-0975DA379BB5}
 		{39CDF34B-FB23-49AE-AB27-0975DA379BB5} = {DFB6ADD7-3149-43D9-AFA0-FC4A818B472B}
-		{FE23BB65-276A-4E41-8CC7-F7752241DEBA} = {39CDF34B-FB23-49AE-AB27-0975DA379BB5}
 		{CBC96CC7-65AB-46EA-A82E-F6A788DABF80} = {F7876C9B-FB6A-4EFB-B058-D6967DB75FB2}
 		{E31F9B59-FCF1-4D04-8762-C7BB60285A7B} = {F7876C9B-FB6A-4EFB-B058-D6967DB75FB2}
 		{6992D926-AB1C-4CD4-94D5-0319D14DB54B} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449}
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 8ee494eeed1..1de2f4309f8 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -86,11 +86,11 @@ stages:
   #                                                  Signed build                                                     #
   #-------------------------------------------------------------------------------------------------------------------#
   - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
-    - ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/release/dev17.8') }}:
+    - ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/release/dev17.9') }}:
       - template: /eng/common/templates/job/onelocbuild.yml
         parameters:
           MirrorRepo: fsharp
-          MirrorBranch: release/dev17.8
+          MirrorBranch: release/dev17.9
           LclSource: lclFilesfromPackage
           LclPackageId: 'LCL-JUNO-PROD-FSHARP'
     - template: /eng/common/templates/jobs/jobs.yml
@@ -713,6 +713,33 @@ stages:
             continueOnError: true
             condition: always()
 
+        # Build benchmarks
+        - job: Plain_Build_Benchmarks
+          pool:
+            name: $(DncEngPublicBuildPool)
+            demands: ImageOverride -equals $(WindowsMachineQueueName)
+          variables:
+          - name: _BuildConfig
+            value: Debug
+          steps:
+          - checkout: self
+            clean: true
+          - script: dotnet --list-sdks
+            displayName: Report dotnet SDK versions
+          - task: UseDotNet@2
+            displayName: install SDK
+            inputs:
+              packageType: sdk
+              useGlobalJson: true
+              includePreviewVersions: true
+              workingDirectory: $(Build.SourcesDirectory)
+              installationPath: $(Agent.ToolsDirectory)/dotnet
+          - script: dotnet build .\FSharp.Benchmarks.sln /bl:\"artifacts/log/$(_BuildConfig)/BenchmarkBuild.binlog\"
+            workingDirectory: $(Build.SourcesDirectory)
+            displayName: Regular rebuild of FSharp.Benchmarks.sln
+            continueOnError: true
+            condition: always()
+
         # Test trimming on Windows
         - job: Build_And_Test_Trimming_Windows
           pool:
@@ -806,8 +833,8 @@ stages:
 - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
   - template: eng/release/insert-into-vs.yml
     parameters:
-      componentBranchName: refs/heads/release/dev17.8
-      insertTargetBranch: main
+      componentBranchName: refs/heads/release/dev17.9
+      insertTargetBranch: rel/d17.9
       insertTeamEmail: fsharpteam@microsoft.com
       insertTeamName: 'F#'
       completeInsertion: 'auto'
diff --git a/buildtools/AssemblyCheck/SkipVerifyEmbeddedPdb.txt b/buildtools/AssemblyCheck/SkipVerifyEmbeddedPdb.txt
index 9ea06757477..f823017f4a1 100644
--- a/buildtools/AssemblyCheck/SkipVerifyEmbeddedPdb.txt
+++ b/buildtools/AssemblyCheck/SkipVerifyEmbeddedPdb.txt
@@ -1,6 +1,5 @@
 FSharp.Build.UnitTests.dll
 FSharp.Compiler.Benchmarks.dll
-Fsharp.ProfilingStartpointProject.dll
 FSharp.Compiler.ComponentTests.dll
 FSharp.Test.Utilities.dll
 FSharp.Compiler.Private.Scripting.UnitTests.dll
diff --git a/docs/content/fsdocs-theme.css b/docs/content/fsdocs-theme.css
new file mode 100644
index 00000000000..78b11777baf
--- /dev/null
+++ b/docs/content/fsdocs-theme.css
@@ -0,0 +1,3 @@
+:root {
+    --main-menu-width: 300px;
+}
diff --git a/docs/fcs/syntax-visitor.fsx b/docs/fcs/syntax-visitor.fsx
deleted file mode 100644
index f0ea0316cfb..00000000000
--- a/docs/fcs/syntax-visitor.fsx
+++ /dev/null
@@ -1,189 +0,0 @@
-(**
----
-title: Tutorial: SyntaxVisitorBase
-category: FSharp.Compiler.Service
-categoryindex: 300
-index: 301
----
-*)
-(*** hide ***)
-#I "../../artifacts/bin/FSharp.Compiler.Service/Debug/netstandard2.0"
-(**
-Compiler Services: Using the SyntaxVisitorBase
-=========================================
-
-Syntax tree traversal is a common topic when interacting with the `FSharp.Compiler.Service`.  
-As established in [Tutorial: Expressions](./untypedtree.html#Walking-over-the-AST), the [ParsedInput](../reference/fsharp-compiler-syntax-parsedinput.html) can be traversed by a set of recursive functions.  
-It can be tedious to always construct these functions from scratch.
-
-As an alternative, a [SyntaxVisitorBase](../reference/fsharp-compiler-syntax-syntaxvisitorbase-1.html) can be used to traverse the syntax tree.
-Consider, the following code sample:
-*)
-
-let codeSample = """
-module Lib
-
-let myFunction paramOne paramTwo =
-    ()
-"""
-
-(**
-Imagine we wish to grab the `myFunction` name from the `headPat` in the [SynBinding](../reference/fsharp-compiler-syntax-synbinding.html).  
-Let's introduce a helper function to construct the AST:
-*)
-
-#r "FSharp.Compiler.Service.dll"
-open FSharp.Compiler.CodeAnalysis
-open FSharp.Compiler.Text
-open FSharp.Compiler.Syntax
-
-let checker = FSharpChecker.Create()
-
-/// Helper to construct an ParsedInput from a code snippet.
-let mkTree codeSample =
-    let parseFileResults =
-        checker.ParseFile(
-            "FileName.fs",
-            SourceText.ofString codeSample,
-            { FSharpParsingOptions.Default with SourceFiles = [| "FileName.fs" |] }
-        )
-        |> Async.RunSynchronously
-
-    parseFileResults.ParseTree
-
-(**
-And create a visitor to traverse the tree:
-*)
-
-let visitor =
-    { new SyntaxVisitorBase() with
-        override this.VisitPat(path, defaultTraverse, synPat) =
-            // First check if the pattern is what we are looking for.
-            match synPat with
-            | SynPat.LongIdent(longDotId = SynLongIdent(id = [ ident ])) ->
-                // Next we can check if the current path of visited nodes, matches our expectations.
-                // The path will contain all the ancestors of the current node.
-                match path with
-                // The parent node of `synPat` should be a `SynBinding`.
-                | SyntaxNode.SynBinding _ :: _ ->
-                    // We return a `Some` option to indicate we found what we are looking for.
-                    Some ident.idText
-                // If the parent is something else, we can skip it here.
-                | _ -> None
-            | _ -> None }
-
-let result = SyntaxTraversal.Traverse(Position.pos0, mkTree codeSample, visitor) // Some "myFunction"
-
-(**
-Instead of traversing manually from `ParsedInput` to `SynModuleOrNamespace` to `SynModuleDecl.Let` to `SynBinding` to `SynPat`, we leverage the default navigation that happens in `SyntaxTraversal.Traverse`.  
-A `SyntaxVisitorBase` will shortcut all other code paths once a single `VisitXYZ` override has found anything.
-
-Our code sample of course only had one let binding and thus we didn't need to specify any further logic whether to differentiate between multiple bindings.
-Let's consider a second example where we know the user's cursor inside an IDE is placed after `c` and we are interested in the body expression of the let binding.
-*)
-
-let secondCodeSample = """
-module X
-
-let a = 0
-let b = 1
-let c = 2
-"""
-
-let secondVisitor =
-    { new SyntaxVisitorBase() with
-        override this.VisitBinding(path, defaultTraverse, binding) =
-            match binding with
-            | SynBinding(expr = e) -> Some e }
-
-let cursorPos = Position.mkPos 6 5
-
-let secondResult =
-    SyntaxTraversal.Traverse(cursorPos, mkTree secondCodeSample, secondVisitor) // Some (Const (Int32 2, (6,8--6,9)))
-
-(**
-Due to our passed cursor position, we did not need to write any code to exclude the expressions of the other let bindings.
-`SyntaxTraversal.Traverse` will check whether the current position is inside any syntax node before drilling deeper.
-
-Lastly, some `VisitXYZ` overrides can contain a defaultTraverse. This helper allows you to continue the default traversal when you currently hit a node that is not of interest.
-Consider `1 + 2 + 3 + 4`, this will be reflected in a nested infix application expression.
-If the cursor is at the end of the entire expression, we can grab the value of `4` using the following visitor:
-*)
-
-let thirdCodeSample = "let sum = 1 + 2 + 3 + 4"
-
-(*
-AST will look like:
-
-Let
- (false,
-  [SynBinding
-     (None, Normal, false, false, [],
-      PreXmlDoc ((1,0), Fantomas.FCS.Xml.XmlDocCollector),
-      SynValData
-        (None, SynValInfo ([], SynArgInfo ([], false, None)), None,
-         None),
-      Named (SynIdent (sum, None), false, None, (1,4--1,7)), None,
-      App
-        (NonAtomic, false,
-         App
-           (NonAtomic, true,
-            LongIdent
-              (false,
-               SynLongIdent
-                 ([op_Addition], [], [Some (OriginalNotation "+")]),
-               None, (1,20--1,21)),
-            App
-              (NonAtomic, false,
-               App
-                 (NonAtomic, true,
-                  LongIdent
-                    (false,
-                     SynLongIdent
-                       ([op_Addition], [],
-                        [Some (OriginalNotation "+")]), None,
-                     (1,16--1,17)),
-                  App
-                    (NonAtomic, false,
-                     App
-                       (NonAtomic, true,
-                        LongIdent
-                          (false,
-                           SynLongIdent
-                             ([op_Addition], [],
-                              [Some (OriginalNotation "+")]), None,
-                           (1,12--1,13)),
-                        Const (Int32 1, (1,10--1,11)), (1,10--1,13)),
-                     Const (Int32 2, (1,14--1,15)), (1,10--1,15)),
-                  (1,10--1,17)), Const (Int32 3, (1,18--1,19)),
-               (1,10--1,19)), (1,10--1,21)),
-         Const (Int32 4, (1,22--1,23)), (1,10--1,23)), (1,4--1,7),
-      Yes (1,0--1,23), { LeadingKeyword = Let (1,0--1,3)
-                         InlineKeyword = None
-                         EqualsRange = Some (1,8--1,9) })
-*)
-
-let thirdCursorPos = Position.mkPos 1 22
-
-let thirdVisitor =
-    { new SyntaxVisitorBase() with
-        override this.VisitExpr(path, traverseSynExpr, defaultTraverse, synExpr) =
-            match synExpr with
-            | SynExpr.Const (constant = SynConst.Int32 v) -> Some v
-            // We do want to continue to traverse when nodes like `SynExpr.App` are found.
-            | otherExpr -> defaultTraverse otherExpr }
-
-let thirdResult =
-    SyntaxTraversal.Traverse(cursorPos, mkTree thirdCodeSample, thirdVisitor) // Some 4
-
-(**
-`defaultTraverse` is especially useful when you do not know upfront what syntax tree you will be walking.  
-This is a common case when dealing with IDE tooling. You won't know what actual code the end-user is currently processing.
-
-**Note: SyntaxVisitorBase is designed to find a single value inside a tree!**  
-This is not an ideal solution when you are interested in all nodes of certain shape.  
-It will always verify if the given cursor position is still matching the range of the node.    
-As a fallback the first branch will be explored when you pass `Position.pos0`.  
-By design, it is meant to find a single result.
-
-*)
diff --git a/docs/fcs/untypedtree-apis.fsx b/docs/fcs/untypedtree-apis.fsx
new file mode 100644
index 00000000000..c713ad8acff
--- /dev/null
+++ b/docs/fcs/untypedtree-apis.fsx
@@ -0,0 +1,553 @@
+(**
+---
+title: Tutorial: AST APIs
+category: FSharp.Compiler.Service
+categoryindex: 300
+index: 301
+---
+*)
+(*** hide ***)
+#I "../../artifacts/bin/FSharp.Compiler.Service/Debug/netstandard2.0"
+(**
+Compiler Services: APIs for the untyped AST
+=========================================
+
+## The ParsedInput module
+
+As established in [Tutorial: Expressions](./untypedtree.html#Walking-over-the-AST), the AST held in a [`ParsedInput`](../reference/fsharp-compiler-syntax-parsedinput.html) value
+can be traversed by a set of recursive functions. It can be tedious and error-prone to write these functions from scratch every time, though,
+so the [`ParsedInput` module](../reference/fsharp-compiler-syntax-parsedinputmodule.html)
+exposes a number of functions to make common operations easier.
+
+For example:
+
+- [`ParsedInput.exists`](../reference/fsharp-compiler-syntax-parsedinputmodule.html#exists)
+    - May be used by tooling to determine whether the user's cursor is in a certain context, e.g., to determine whether to offer a certain tooling action.
+- [`ParsedInput.fold`](../reference/fsharp-compiler-syntax-parsedinputmodule.html#fold)
+    - May be used when writing analyzers to collect diagnostic information for an entire source file.
+- [`ParsedInput.foldWhile`](../reference/fsharp-compiler-syntax-parsedinputmodule.html#foldWhile)
+    - Like `fold` but supports stopping traversal early.
+- [`ParsedInput.tryNode`](../reference/fsharp-compiler-syntax-parsedinputmodule.html#tryNode)
+    - May be used by tooling to get the last (deepest) node under the user's cursor.
+- [`ParsedInput.tryPick`](../reference/fsharp-compiler-syntax-parsedinputmodule.html#tryPick)
+    - May be used by tooling to find the first (shallowest) matching node near the user's cursor.
+- [`ParsedInput.tryPickLast`](../reference/fsharp-compiler-syntax-parsedinputmodule.html#tryPickLast)
+    - May be used by tooling to find the last (deepest) matching node near the user's cursor.
+
+## SyntaxVisitorBase & SyntaxTraversal.Traverse
+
+While the `ParsedInput` module functions are usually the simplest way to meet most needs,
+there is also a [`SyntaxVisitorBase`](../reference/fsharp-compiler-syntax-syntaxvisitorbase-1.html)-based API that can
+provide somewhat more fine-grained control over syntax traversal for a subset of use-cases at the expense of a bit more
+ceremony and complexity.
+
+## Examples
+
+Let's start by introducing a helper function for constructing an AST from source code so we can run through some real examples:
+*)
+
+#r "FSharp.Compiler.Service.dll"
+open FSharp.Compiler.CodeAnalysis
+open FSharp.Compiler.Text
+open FSharp.Compiler.Syntax
+
+let checker = FSharpChecker.Create()
+
+/// A helper for constructing a `ParsedInput` from a code snippet.
+let mkTree codeSample =
+    let parseFileResults =
+        checker.ParseFile(
+            "FileName.fs",
+            SourceText.ofString codeSample,
+            { FSharpParsingOptions.Default with SourceFiles = [| "FileName.fs" |] }
+        )
+        |> Async.RunSynchronously
+
+    parseFileResults.ParseTree
+
+(**
+### ParsedInput.exists
+
+Now consider the following code sample:
+*)
+
+let brokenTypeDefn = """
+module Lib
+
+// Whoops, we forgot the equals sign.
+type T { A: int; B: int }  
+"""
+
+(**
+Let's say we have a code fix for adding an equals sign to a type definition that's missing one—like the one above.
+We want to offer the fix when the user's cursor is inside of—or just after—the broken type definition.
+
+We can determine this by using `ParsedInput.exists` and passing in the position of the user's cursor:
+*)
+
+// type T { A: int; B: int } 
+// ···········↑
+let posInMiddleOfTypeDefn = Position.mkPos 5 12
+
+(**
+Given that cursor position, all we need to do is find a `SynTypeDefn` node:
+*)
+
+let isPosInTypeDefn = // true.
+    (posInMiddleOfTypeDefn, mkTree brokenTypeDefn)
+    ||> ParsedInput.exists (fun _path node ->
+        match node with
+        | SyntaxNode.SynTypeDefn _ -> true
+        | _ -> false)
+
+(**
+If the position passed into `ParsedInput.exists` is not contained in any node in the given AST,
+but rather is below or to the right of all nodes, `ParsedInput.exists` will fall back to exploring the nearest branch above
+and/or to the left. This is useful because the user's cursor may lie beyond the range of all nodes.
+*)
+
+// type T { A: int; B: int }  
+// ··························↑
+let posAfterTypeDefn = Position.mkPos 5 28
+
+(**
+Our function still returns `true` if the cursor is past the end of the type definition node itself:
+*)
+
+let isPosInTypeDefn' = // Still true.
+    (posAfterTypeDefn, mkTree brokenTypeDefn)
+    ||> ParsedInput.exists (fun _path node ->
+        match node with
+        | SyntaxNode.SynTypeDefn _ -> true
+        | _ -> false)
+
+(**
+### ParsedInput.fold
+
+`ParsedInput.fold` can be useful when writing an analyzer to collect diagnostics from entire input files.
+*)
+
+(*** hide ***)
+let getLineStr (line: int) : string = failwith "Nope."
+
+(**
+Take this code that has unnecessary parentheses in both patterns and expressions:
+*)
+
+let unnecessaryParentheses = """
+let (x) = (id (3))
+"""
+
+(**
+We can gather the ranges of all unnecessary parentheses like this:
+*)
+
+open System.Collections.Generic
+
+module HashSet =
+    let add item (set: HashSet<_>) =
+        ignore (set.Add item)
+        set
+
+let unnecessaryParenthesesRanges =
+   (HashSet Range.comparer, mkTree unnecessaryParentheses) ||> ParsedInput.fold (fun ranges path node ->
+       match node with
+       | SyntaxNode.SynExpr(SynExpr.Paren(expr = inner; rightParenRange = Some _; range = range)) when
+           not (SynExpr.shouldBeParenthesizedInContext getLineStr path inner)
+           ->
+           ranges |> HashSet.add range
+
+       | SyntaxNode.SynPat(SynPat.Paren(inner, range)) when
+           not (SynPat.shouldBeParenthesizedInContext path inner)
+           ->
+           ranges |> HashSet.add range
+
+       | _ ->
+           ranges)
+
+(**
+### ParsedInput.tryNode
+
+Sometimes, we might just want to get whatever node is directly at a given position—for example, if the user's
+cursor is on an argument of a function being applied, we can find the node representing the argument and use its path
+to backtrack and find the function's name.
+*)
+
+let functionApplication = """
+f x y  
+"""
+
+(**
+If we have our cursor on `y`:
+*)
+
+// f x y
+// ·····↑
+let posOnY = Position.mkPos 2 5
+
+(**
+The syntax node representing the function `f` technically contains the cursor's position,
+but `ParsedInput.tryNode` will keep diving until it finds the _deepest_ node containing the position.
+
+We can thus get the node representing `y` and its ancestors (the `path`) like this:
+*)
+
+let yAndPath = // Some (SynExpr (Ident y), [SynExpr (App …); …])
+    mkTree functionApplication
+    |> ParsedInput.tryNode posOnY
+
+(**
+Note that, unlike `ParsedInput.exists`, `ParsedInput.tryPick`, and `ParsedInput.tryPickLast`,
+`ParsedInput.tryNode` does _not_ fall back to the nearest branch above or to the left.
+*)
+
+// f x y
+// ······↑
+let posAfterY = Position.mkPos 2 8
+
+(**
+If we take the same code snippet but pass in a position after `y`,
+we get no node:
+*)
+
+let nope = // None.
+    mkTree functionApplication
+    |> ParsedInput.tryNode posAfterY
+
+(**
+### ParsedInput.tryPick
+
+Now imagine that we have a code fix for converting a record construction expression into an anonymous record construction
+expression when there is no record type in scope whose fields match.
+*)
+
+let recordExpr = """
+let r = { A = 1; B = 2 }
+"""
+
+(**
+We can offer this fix when the user's cursor is inside of a record expression by
+using `ParsedInput.tryPick` to return the surrounding record expression's range, if any.
+*)
+
+// let r = { A = 1; B = 2 }
+// ······················↑
+let posInRecordExpr = Position.mkPos 2 25
+
+(**
+Here, even though `ParsedInput.tryPick` will try to cleave to the given position by default,
+we want to verify that the record expression node that we've come across actually contains the position,
+since, like `ParsedInput.exists`, `ParsedInput.tryPick` will also fall back to the nearest branch above and/or
+to the left if no node actually contains the position. In this case, we don't want to offer the code fix
+if the user's cursor isn't actually inside of the record expression.
+*)
+
+let recordExprRange = // Some (2,8--2,24).
+    (posInRecordExpr, mkTree recordExpr)
+    ||> ParsedInput.tryPick (fun _path node ->
+        match node with
+        | SyntaxNode.SynExpr(SynExpr.Record(range = range)) when
+            Range.rangeContainsPos range posInRecordExpr
+            -> Some range
+        | _ -> None)
+
+(**
+We might also sometimes want to make use of the `path` parameter. Take this simple function definition:
+*)
+
+let myFunction = """
+module Lib
+
+let myFunction paramOne paramTwo =
+    ()
+"""
+
+(**
+Imagine we want to grab the `myFunction` name from the `headPat` in the [`SynBinding`](../reference/fsharp-compiler-syntax-synbinding.html).
+
+We can write a function to match the node we're looking for—and _not_ match anything we're _not_ looking for (like the argument patterns)—by taking its path into account:
+*)
+
+let myFunctionId = // Some "myFunction".
+    (Position.pos0, mkTree myFunction)
+    ||> ParsedInput.tryPick (fun path node ->
+        // Match on the node and the path (the node's ancestors) to see whether:
+        //   1. The node is a pattern.
+        //   2. The pattern is a long identifier pattern.
+        //   3. The pattern's parent node (the head of the path) is a binding.
+        match node, path with
+        | SyntaxNode.SynPat(SynPat.LongIdent(longDotId = SynLongIdent(id = [ ident ]))),
+          SyntaxNode.SynBinding _ :: _ ->
+            // We have found what we're looking for.
+            Some ident.idText
+        | _ ->
+            // If the node or its context don't match,
+            // we continue.
+            None)
+
+(**
+Instead of traversing manually from `ParsedInput` to `SynModuleOrNamespace` to `SynModuleDecl.Let` to `SynBinding` to `SynPat`, we leverage the default navigation that happens in `ParsedInput.tryPick`.  
+`ParsedInput.tryPick` will short-circuit once we have indicated that we have found what we're looking for by returning `Some value`.
+
+Our code sample of course only had one let-binding and thus we didn't need to specify any further logic to differentiate between bindings.
+
+Let's consider a second example involving multiple let-bindings:
+*)
+
+let multipleLetsInModule = """
+module X
+
+let a = 0
+let b = 1
+let c = 2
+"""
+
+(**
+In this case, we know the user's cursor inside an IDE is placed after `c`, and we are interested in the body expression of the _last_ let-binding.
+*)
+
+// …
+// let c = 2
+// ·····↑
+let posInLastLet = Position.mkPos 6 5
+
+(**
+Thanks to the cursor position we passed in, we do not need to write any code to exclude the expressions of the sibling let-bindings.
+`ParsedInput.tryPick` will check whether the current position is inside any given syntax node before drilling deeper.
+*)
+
+let bodyOfLetContainingPos = // Some (Const (Int32 2, (6,8--6,9))).
+    (posInLastLet, mkTree multipleLetsInModule)
+    ||> ParsedInput.tryPick (fun _path node ->
+        match node with
+        | SyntaxNode.SynBinding(SynBinding(expr = e)) -> Some e
+        | _ -> None)
+
+(**
+As noted above, `ParsedInput.tryPick` will short-circuit at the first matching node.
+`ParsedInput.tryPickLast` can be used to get the _last_ matching node that contains a given position.
+
+Take this example of multiple nested modules:
+*)
+
+let nestedModules = """
+module M
+
+module N =
+    module O =
+        module P = begin end
+"""
+
+(**
+By using `ParsedInput.tryPick`, we'll get the name of the outermost nested module even if we pass in a position inside the innermost,
+since the innermost is contained within the outermost.
+
+This position is inside module `P`, which is nested inside of module `O`, which is nested inside of module `N`,
+which is nested inside of top-level module `M`:
+*)
+
+// module M
+//
+// module N =
+//     module O =
+//         module P = begin end
+// ···························↑
+let posInsideOfInnermostNestedModule = Position.mkPos 6 28
+
+(**
+`ParsedInput.tryPick` short-circuits on the first match, and since module `N` is the first
+nested module whose range contains position (6, 28), that's the result we get.
+*)
+
+let outermostNestedModule = // Some ["N"].
+    (posInsideOfInnermostNestedModule, mkTree nestedModules)
+    ||> ParsedInput.tryPick (fun _path node ->
+        match node with
+        | SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longId))) ->
+            Some [for ident in longId -> ident.idText]
+        | _ -> None)
+
+(**
+### ParsedInput.tryPickLast
+
+If however we use the same code snippet and pass the same position into `ParsedInput.tryPickLast`,
+we can get the name of the _last_ (deepest or innermost) matching node:
+*)
+
+let innermostNestedModule = // Some ["P"].
+    (posInsideOfInnermostNestedModule, mkTree nestedModules)
+    ||> ParsedInput.tryPickLast (fun _path node ->
+        match node with
+        | SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longId))) ->
+            Some [for ident in longId -> ident.idText]
+        | _ -> None)
+
+(**
+If we want the next-to-innermost nested module, we can do likewise but make use of the `path` parameter:
+*)
+
+let nextToInnermostNestedModule = // Some ["O"].
+    (posInsideOfInnermostNestedModule, mkTree nestedModules)
+    ||> ParsedInput.tryPickLast (fun path node ->
+        match node, path with
+        | SyntaxNode.SynModule(SynModuleDecl.NestedModule _),
+          SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longId))) :: _ ->
+            Some [for ident in longId -> ident.idText]
+        | _ -> None)
+
+(**
+### SyntaxTraversal.Traverse
+
+Consider again the following code sample:
+*)
+
+let codeSample = """
+module Lib
+
+let myFunction paramOne paramTwo =
+    ()
+"""
+
+(**
+Imagine we wish to grab the `myFunction` name from the `headPat` in the [SynBinding](../reference/fsharp-compiler-syntax-synbinding.html).  
+
+We can create a visitor to traverse the tree and find the function name:
+*)
+
+let visitor =
+    { new SyntaxVisitorBase() with
+        override this.VisitPat(path, defaultTraverse, synPat) =
+            // First check if the pattern is what we are looking for.
+            match synPat with
+            | SynPat.LongIdent(longDotId = SynLongIdent(id = [ ident ])) ->
+                // Next we can check if the current path of visited nodes, matches our expectations.
+                // The path will contain all the ancestors of the current node.
+                match path with
+                // The parent node of `synPat` should be a `SynBinding`.
+                | SyntaxNode.SynBinding _ :: _ ->
+                    // We return a `Some` option to indicate we found what we are looking for.
+                    Some ident.idText
+                // If the parent is something else, we can skip it here.
+                | _ -> None
+            | _ -> None }
+
+let result = SyntaxTraversal.Traverse(Position.pos0, mkTree codeSample, visitor) // Some "myFunction"
+
+(**
+Instead of traversing manually from `ParsedInput` to `SynModuleOrNamespace` to `SynModuleDecl.Let` to `SynBinding` to `SynPat`, we leverage the default navigation that happens in `SyntaxTraversal.Traverse`.  
+A `SyntaxVisitorBase` will shortcut all other code paths once a single `VisitXYZ` override has found anything.
+
+Our code sample of course only had one let binding and thus we didn't need to specify any further logic whether to differentiate between multiple bindings.
+
+### SyntaxTraversal.Traverse: using position
+
+Let's now consider a second example where we know the user's cursor inside an IDE is placed after `c` and we are interested in the body expression of the let binding.
+*)
+
+let secondCodeSample = """
+module X
+
+let a = 0
+let b = 1
+let c = 2
+"""
+
+let secondVisitor =
+    { new SyntaxVisitorBase() with
+        override this.VisitBinding(path, defaultTraverse, binding) =
+            match binding with
+            | SynBinding(expr = e) -> Some e }
+
+let cursorPos = Position.mkPos 6 5
+
+let secondResult =
+    SyntaxTraversal.Traverse(cursorPos, mkTree secondCodeSample, secondVisitor) // Some (Const (Int32 2, (6,8--6,9)))
+
+(**
+Due to our passed cursor position, we did not need to write any code to exclude the expressions of the other let bindings.
+`SyntaxTraversal.Traverse` will check whether the current position is inside any syntax node before drilling deeper.
+
+### SyntaxTraversal.Traverse: using defaultTraverse
+
+Lastly, some `VisitXYZ` overrides can contain a defaultTraverse. This helper allows you to continue the default traversal when you currently hit a node that is not of interest.
+Consider `1 + 2 + 3 + 4`, this will be reflected in a nested infix application expression.
+If the cursor is at the end of the entire expression, we can grab the value of `4` using the following visitor:
+*)
+
+let thirdCodeSample = "let sum = 1 + 2 + 3 + 4"
+
+(*
+AST will look like:
+
+Let
+ (false,
+  [SynBinding
+     (None, Normal, false, false, [],
+      PreXmlDoc ((1,0), Fantomas.FCS.Xml.XmlDocCollector),
+      SynValData
+        (None, SynValInfo ([], SynArgInfo ([], false, None)), None,
+         None),
+      Named (SynIdent (sum, None), false, None, (1,4--1,7)), None,
+      App
+        (NonAtomic, false,
+         App
+           (NonAtomic, true,
+            LongIdent
+              (false,
+               SynLongIdent
+                 ([op_Addition], [], [Some (OriginalNotation "+")]),
+               None, (1,20--1,21)),
+            App
+              (NonAtomic, false,
+               App
+                 (NonAtomic, true,
+                  LongIdent
+                    (false,
+                     SynLongIdent
+                       ([op_Addition], [],
+                        [Some (OriginalNotation "+")]), None,
+                     (1,16--1,17)),
+                  App
+                    (NonAtomic, false,
+                     App
+                       (NonAtomic, true,
+                        LongIdent
+                          (false,
+                           SynLongIdent
+                             ([op_Addition], [],
+                              [Some (OriginalNotation "+")]), None,
+                           (1,12--1,13)),
+                        Const (Int32 1, (1,10--1,11)), (1,10--1,13)),
+                     Const (Int32 2, (1,14--1,15)), (1,10--1,15)),
+                  (1,10--1,17)), Const (Int32 3, (1,18--1,19)),
+               (1,10--1,19)), (1,10--1,21)),
+         Const (Int32 4, (1,22--1,23)), (1,10--1,23)), (1,4--1,7),
+      Yes (1,0--1,23), { LeadingKeyword = Let (1,0--1,3)
+                         InlineKeyword = None
+                         EqualsRange = Some (1,8--1,9) })
+*)
+
+let thirdCursorPos = Position.mkPos 1 22
+
+let thirdVisitor =
+    { new SyntaxVisitorBase() with
+        override this.VisitExpr(path, traverseSynExpr, defaultTraverse, synExpr) =
+            match synExpr with
+            | SynExpr.Const (constant = SynConst.Int32 v) -> Some v
+            // We do want to continue to traverse when nodes like `SynExpr.App` are found.
+            | otherExpr -> defaultTraverse otherExpr }
+
+let thirdResult =
+    SyntaxTraversal.Traverse(cursorPos, mkTree thirdCodeSample, thirdVisitor) // Some 4
+
+(**
+`defaultTraverse` is especially useful when you do not know upfront what syntax tree you will be walking.  
+This is a common case when dealing with IDE tooling. You won't know what actual code the end-user is currently processing.
+
+**Note: SyntaxVisitorBase is designed to find a single value inside a tree!**  
+This is not an ideal solution when you are interested in all nodes of certain shape.  
+It will always verify if the given cursor position is still matching the range of the node.    
+As a fallback the first branch will be explored when you pass `Position.pos0`.  
+By design, it is meant to find a single result.
+
+*)
diff --git a/docs/img/favicon.ico b/docs/img/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..ad06a8a28037228e4e1f8f5f5d242a1974f2d25d
GIT binary patch
literal 107697
zcmeHw2V76z|NpJX-XAL~GDAkPDO=eIMTk%tl{6%j9ZDG`qs-D$8KI#fR3el_sgTf;
zC@p#ad-naE@Be=9=RNNG-4HsDN8R_m_uMmHuh)5<*E;7=lo%yRA&F7a)TC|{wWj>H
zmDPXl`!*D#Jj$ObDgEF5M2dRWM~oUg_&@jVy(p?!ul!5t|GRHVQRnQ$sFvkdl&4#d
zqLj~yQTyl4p4P0fRO9lZn<-D9tcthzYgqoDGVfRzNKxGyD^H%FwmC6p+s92Z%BCNq
zW&fG$x4XMo%bt;L1||A8PJJG-_;JiyYHh!k$$m@!w*TjtALec1K8syH
z^;29asKHbHk|tD6SEZngLDY2%D#tC9dWx5eCBq(2?{1wssC`gI$N6Tqm3Nz^BiikF
zAsI8;LbCj>aPPJeZFjtQkYhc5MJsCe_^t1BNA$^|!W75on3o+l`+ny1`XKWmohUc$
zp)0q28}TmujHyQAW19fVFXoPWCufe%nUf7uC)YdKRo-Z~j)w7D%O{h3wz^$E)h+ya
ze$!7KN}ujb;k?gNl+;gI_B7kNEKa7`#3zYmEhem!ZxLip`T6AOH}K^AlQ*u#mi0Lw
zBBd32NvP{Q@vE<}{m^=|Rq3~0=({wXH(x$1<(u`Sdj_2g&(uqLd}PSlHIhXU`#f&G
zim>=utgbs^kz{01Q>B!su5DiqaG6u8e`N9c&60kH-Y#o!-qP;Yo#0-}^hYdTBuS+;
zoO5M*L2G@-wrMMaI>tS=zmt_5-fgk{1BDl3EJv7X59_f@K1{J={EGY`&YT6K``$RE
zux-_+Syw*q*AIG8+JN%g+^w0(bv#@p=@;|KYC#JQrK@I@Gco8y(0Z!qi$wBq`T27B
z^UH5nQCrirB~Ookq;)fGwQF+r(jHXgn6^WDCtkL@cX?(|anLYIy;Rq3erkzgXs?ms
z>s@Y~x-&!EYUAGC9khQ)gbm)AXp-8@MEp&lLV``4S!8N)mg%O={ivcoC8suZH682z
z!}xZ(Ro8$An|t>dn-hJtsk-;W>q|Do#U>&zu@%YZFv5}HXxG~_37r(uM`T7
zcu2g-EVaty^vih?`mxZn>$UD{H6uHIS{C54anb_nM_d~(0r1{b|uX@93Dg@8VuZTQyEF=s5RgQArVJ%H8%c?;}1gvw*QuNH$5YbnRVCEkv`k$P6PN9_u0EA@`oPotZd-30?n{;bwi(^Q
zU4oj?>(kk_lWoG!zxQb`KDndPL5>6!8K0coni}l$d0wnrpY$_Gl+rEwO2=xceC~YVNoz&*WEo{|vEBG&v&Clln0~u5(UFeo2$^
z=5Dgg_P4v(igNFADMPB&x=?4iNI=crl$%$9^99`zb;MMz5UL$d6uqQ
z{JK+=k?|AHKD(m!7r%
zONR{Y$GJO3slf4CnN6^2h-BkCQ>f?fIPn+G45q9G4!ty@i+a?yfyw9AJkrpwuX1Ib
zz1o%)jf&hps}|2O_+c$ZjV+AGdat;l5k;vrpOcYdwCdCVhomz~hRvz3vkGE!LSHUx
zMs@qBG?_K|$4XJlm
zj{AmAHEE<2@#xanvZQOdXKpO*vZYTwhxt)cIt|F$w5C2~)n=8~(JW7D^2hORi4JF1
z{nY*@)o22x+;Z$c3Y3QTq3b)vdQP~JWFpbhIV8t*d%ugJuRN}&O5gI!dn+F`WWCHf
zIU5VGL8+d(G%duY8)ZE8Kr`tcC
zlG#-0N4B*v>I7o9+eQD#|O>Lbw=8l-5
z8f4ywqHguQrPpw9^N$|&sJU~C%#PSgDy3#G4gAsm2*-SB=Gx3Mv7OT9dR|s(Cr>{atRQ^mmQ&r3B#zjU;Z%JmIsYg9G>N=*Gn3rPz=^f6hz6~~r>%G5xCMrED
z`!!c9-8`w#QkIhL6>R$O-4w^qM)T@fC7$D4o;tZ+*toJ22Y;RlQVac9
zvY7S$jk~>Cob}ZOjVM{2uI&#>t)aAoN~M*`M(M3vaV~j4mKb&H*5e6z>C!XmeVk0$
zziaMdK%M>e`J?QRU6)b~{7-3bqo|mJ#z{}pAC*fPI!rB@4l%?+PDp~(6#iLc=kLc`>N4nXT-r+eJ`K7_j
zJk*C?dcHGL^1hD3oNo6&YinM()TdYdH)>Zm4+>U&G0J?&l%F{R^gZ)pj7}%#9g{BTkR$KW<>%dh
z8r_-wuE0x9F`@nY!)D8z6}}ngeHo!VPD8rKYFoplo3h&)>?xtbiYI$FN}6mlD8%zq
zfbG?KRs}JEzPDz%#%yhH+QQ`GL5G7EFFIO2%nVd@8<#lBG`_4jzxP(Hx1BDOT{-ry
zeUs6J8)dJzdot~@smJ6Jsji>SXvIeVa7qZH?mY_alG)5M{!>z!vG+@x&Z`1T#Vw!8
z>ooKBdno2&nAJ|%p)6e{`RyQw9i}r^$?tX6_Wt(S@ZN(*I@d4vlc3zwTMU~!Fy!j_
z)N|*aw(@J|oS%{7jf?&O1uB&@m=6@^WIHn2@u
zQl4}ZD$Hi|#LyR>i$~mwet0GG)}n8oUw_`5GU@G{DYg@GU*4WH!Lg^tk?Wh*c1}(!
z3^zF1ao!h~oJCRwccrOY_F8@XjdnLq@_qNfd!+I#%_U>HooRfvr^?m258KXYtL(PF
z={?itHitALV{g{a?dcfnsXfF~=k4pgH>b4~8*s1vh^C9Lc&5uljvp9xwMYM}YNKcC
zTy<4(Rh8LqwztL1n5IQ?jr%S6bo8XRl+9po-FKOVbGDq8ZQpla=nSdm9Ix3M?m0I|
zGT1es=h1x@NfEopbS^uS?BT1na_Zr%B?_aS?sgkkHga^P>-HroKW0P?<|vez`E9+f
zv)DUZ|GwSPul4`2*D*4EJ?+curZ2-oRrN|zY&_;2jBeBQp}y0rWdo#co?IoN+O_*$
z|HR90_s5l8exIbWYHy+Cu;)3wTvw})?$bEbb_fdmE>*&#_g7gYe@MH`C_^|
zdRubdFnY|O@247N%04idxX{aN
zuz#6RzyPh`BjqhlEjzIyhjVP{S(9PwViF(3F4}ZcDm*OyvE@2Bmp%#~f3BIh)GY1E
z@Nc^;I~lplx@)&9<+y6S_70k`eS!Y;-Q$ygxOrqxJNQxgTC;=>>&|c{^y~1{Gi~$*
zDYeJqN|D`09=g5up<%)I*>e)OWg7ckurEUYIy3K
z{7JhWk4}|Y6_?+!U#B5!Ck1^Nr*Bd$u{ked&FDVozocbs_u1dc)<*5L-TZ_#{pF@*
z1ep~}oNyR)s^uyhv+U6NKBMa$IB0p`naLf;tv>HuhW#w@E%SHieRX-jr{}xmwwbsO
zoZBmJm&)A*GpKSN_G2j3^IfM|#5qiz3aH{an_-4(QSHYt?qt!
z_|`!y%k11Nd_tO8=4dHj9)0b;pM+yOv16L@ug+*DD5fZ+4LEdpPcwhtB-63#5k*J)
zg%m{Ss;<~RWx<$r?Wx!AZ?`fjXzMp1LDu#BfEgV+?DZd&-P~n`&E<|Zi@ra%c2P$S~SYDjBo6DU4r`OM8J#%mVUwh!4|50W5pjB6&SC$>6JU_O!NA!yZQFH
z?xWX$+Ogka!hr$v4`l3$Prk0A+R-t6t(=Kwj-9dIUR~KG{ZG#GA5Lj?43wY!VfkUB
zQr~vp6>J*^sLyPAXjaptfu0uP<290=t37?(z^c)Btdew}Svd_zhKQZ2?cI@FY@0E-6CUp1t`B^<_qI?(X
z$(unx?&&Sk*cxcK>f+h1GaR^P<4+53Oi{@z&fFMxzq^Bs>$kM2;jyu!
zu3o&Pm)3Uks=2o|o|@EfNYm)W1L{$RCZ!RRo7^Aba3Qxvr%k#YIO_X+WQ^syQNuG8
zjBgwM$h8>g95Oel=&}BVk~f*Bo*rGbrFaX~W^3!=M%2xsOtU7J9j9De72@@F!O)n?
zS8wz%E*?tNA3L=uB520Cfg{u}>wii4S<>Q_OUU^fzTdwdr`niGO;8BB>Zl(ubFs3|
zxHeg5?i$-jUZ3?Lx`9=WSqJk^FJ=^IJGETdVeg6#7atzn{H1hj_~?}plM-bDe)I}E
z)Y0(!%Hl%Lj`0oiI!E*fyQhe@=kX#okrp>S~k7849Je1UG
zwA&(R>1-D}3H$0{zacE1ggIR~%=G&Cr6N<%C4trBtZO^Yu#
zKCf!|ew552f7P5p7Ls3k^k#T%voltew~4
zoo277Tia%rwU3CJ;?Q?&nftzWoRvirY%bQ@@1-L9)*~$<@&2Ot__xuLVd=yD8f3SA
zvUFn1l@^idk+ZwlJZ$y4okkkVU8SkWOG9G)BTKH$dH!vx
z)3YaC+l23O*rS=8sI_#vZBy^)c02D+ws|`s@Posxq9gfT2bx)?cn#6ro0}rNAaRA>
z!-9}THZL9K7bu0V9<(D-PvdpR>=s#lquV#1zS_ilot(St44HL?fm26%PwVFz{&_SN
zIBaHIv?O)#-Pfp%YX^LK{_v-&=f0jJ?8g};o%2v0eB;Eujv0o>FWlMUeOGGP;r?G5
zy<4?5pzzyas|OccV~4D0C&QUJcc13On+db0PraA2zN}BHZ(>wfx@}pAM}Yf+oCPZP
z+lW(|`M$=kiiT#5d;a+T)hIbVocpQ1$zQiKX{c-x*QFp`U_Vt$E_%i<06iP{UQ6{A|^2R`l
z>g$jb9`bB|E0@;yd=DR^hQF*|68WJ?o5dUYxk@G>gf6
zD8r(0XYK6AOe|9C7w^?B(lh2=eDCR6-M@89Z80ag`-b&Hque&#GU;PCdb)GavBlx@
zH)I|NYpY|e70`1*T!S`m9~>CogBl*Be>~83*doJSAM9?K#*`aV7iVUVw6JjRK5%jO
z6W7~$eHPnzF<@u<-b;xarazV*-hEobCQ)%0R2G$Ow^3dwH8HSEd4O`b-f6L?Z)bUS
zFmI3U
zhO4y|XY5xzSN0j4K$EoT8&G(JFezTKI(B7G+#F|Ch_lhcA
zJLPFmi^e@IWqSnluvd@@Zabwm`MWu{O$7U)6A*Cr4jLq#MhfPuobHeLsEmNt=Toj!yAuq2Fg&@S}LUaBnq@fC;Pe
zE*9-DI?_3zFf6fSzt2&l-Ocl@zr7k=^1^I(%7|u<#Ff^oU%AnIr}KgN5ev56NuPM&
z*bl9Zu}vDaOn94Df8v;u1E{slau04=(kSR##)_#4Qehb~s;+XmYI|A~kKSv?
zx#bw(*WJmX|9X>{_-k`zOdj8FIJH1`m%pN%z3GlCC(f2^i)`nVxv5cZ;#Q~nR`*NX
zRg(&u5sV^RQ)!AySpd#X|+K?e52{jCmW70dm?>pm6ck|t5nXwdj*HHhXwq&nvkh#
z*}SmXGejc^9+dM8l;c&5+Z}PTTDgoz?+OD?RJU%G63mji`&m~j+Y24SrhtjUXMjay|%y4X}l+Swu{7-#j`KX*K@eH==qq}
z9!tchzq)oabZrkR{`tH~vqQB%EgUfI_N1Av3El&urNa&kQ1NU&|ASBSfkgx3TYoI>
z)mz-E#rBhzea)w3e{}FvkyvSCa^upq5=$T7v>_BFXW$~Cl{ma%xt*ZkLH(^+Ki~AK
zC*fUYdEwjG_2qUY9-tv;l$wWn^mv$SQ1)f=LJ?GxyG4q=wn~z-iewNEpzh1NC
z&iI-Re-U#n=I1Vz{tdsh;mEAL*sIf_GULrZ?V`H$JTxb|*|Hh;rnsDa{K2k=S;5xM
zx{szscloUCxVq)O4vwqUCB2)j9I2%tsT|eBdC)9LE49&0ZMNO$+f~;rNc!kCgDsxV
z_VvEse&LlptL@ufY1dAp!>ZM-!n-#K_ltd?5kx7KU7U2E+S7H+&z1?@I)qGjbg{5&
zG{h}7w#niKU0xUs84<2VsYeWwdH-_hOU2UAgeDJKX?a_gEt=fs4QHI<`DB^UOEymZ
z>K*?0c9Kfh!7GdGdvqB8FtT;YmpHkdEi^_JEB13<8ULuGR*TdN?Hq=_*na1Bpx%0U
z!^wR<1U71Hf7;yie4$l~Hey;^C*54o)HG>>-IAFLO-7tpQ||J3J@eS$3x-3+`(CiL
z$)MEtDbDpz81T#|DRh4?lf{aWQk(Owx4u6Z{LOgD&5=V|StZF!?fck0B=<~fUzglW
z54Vr|diQQH@}19tM0!4
zWUJXL+ELbBx@J6ok*VUCyLWKH$|bVhiL_MC{y??wM}EZm+M4tn+K5`h8MIkOvj5ir{YIgEkADqVKda@GHzQ-x
zH(HF|e9GaP=h#p0la5O+(L5zVHMYy|wCT3`08>iCeWA*cp8dnr)xDfQ=41w3U-^B`
z!A85*xQ?RK8%!-|H&L_a3;l%U2bxQ-a{Ot$^11u423BE3PCw7ix_0rj9B17Nzj3Q2
zsivIe4+{M6Y}j*ek7AkHQ2jY4#i$Y9GA15Vj_m1nCRgp`m%dKrCfO5BmgPOWGIwUK
z<;_L9?`#^#Q-0IBc369P)#+mo?|h9*{_y$s7HWV*w^Cn6%Tb)tJ!NZ3pDi6nExmc^
zdeI^k&qQ0v^umy31Bd4<93f_9KlQ~Kr_@BldKbn$b{XojSaaOEH3g^YQ$FpU&u(qs
z-{ba2ukVqOYGJO0GgAvaoOIK7mw1^SXxB3+ah|NdbFt$37Y{R>>qX~Hm1^ZOe{_o4
zq{I=%1@dRFZtkggUSp^KBgKfTt*OZL_=2#o+ZxC7#LhXE+jI0c4scs9_Jd11!!
zD`pYz4g?fs&R(oFO1rabn#Dky7@LRB5>xD~^+rzaI-}VC@nvVT2c6pO{xNUmpyx^H
zg(FAqjc+0mcjUy1y|Om<+a7ZEh}-LssgZrEELhcS_0TTg_H3~bmvgzPF~IuSycyBg
z@9i4(LaV@hVafZl5sPgeKRMcXaoe}=SGCdz6yKqAG5XFDh34~gPdxJMoLuTKwlL<#
zaj*W0>(f8gzpXx6`HHuLcE@`|Ps@Cn;lF*Z<_t$SW$I00hS`r#okm$jM=fenYOYYI
z=(xJof|lY+)^86*M2yKuxN)P2Q~E#mCwfon*g~3WIj6<&~+tTGFwWsG_@(ioKIth9M^X{TJkDIsx5WHRes5=
zS%>e$8XYxTXxFamvwy_hTzhG)antR8Z27qxZ}bN~&UY(!0{ygib5QZSJTvW-IOXWr
z;=p^~mf_b2H_~rRS=o)y`#3lwcbxH2F-mXT?1g8V4qG1hj8fWaa_W(|PT3}Paq8~(
zYYSUw2fU*CzDkyOH}&Ze1>;?m)mkI}scXZdZmevU+>J^Nz6)fK!+7W9$Z!Lzp8cV{#7CI^F8%DP!9ujV*98axD?$WW8wt;VjG`M4Jfsn
zoNJ|nPed)4qA^cy2d7g5E2EO3j)N90)+iX!iR!!PO{`PsVMTUN9Su|u4Q$!6
zg>&@iQI3(35oh`G
z96o%QV_;ywS-g009Uc6^ba3Lt3C{QL-#PRIS|}(e;C%Y@i4zwW$GLRr635EQs)8@n
z@!;y=!M_5oD_5@MBqt}+QP1`F&!0azNl8hZ6)RTM@q#~u7pSYNbIzVU%PB1_<%)CW
z!<3X1j+T~I9sd6i{OjxMb6&rG%|tWLd*ofVY*`)t{{Z|$w)gSz;r#gVgD1Y3FCZ7z
z$%22z+;3=T$ocT$0~5u3?-LRd>g2yaVC-vZYI6Mj{VVi6z6fW$eE$4-9q+GV{6n60
zc6R2NnwoMTkJW?@U}0gw$;!%NU{~;MOiWCTw67*$P#fx4vt|t^ARwSZ{)V0nI?&eE
zu2vW?S+ax^5)vX9*<5l&MMYI>+iC+&YN`#ZR;}WMg@tj7i;MpY>B7Q7&a-FFIJlEh4y?gg6-KNU+=}-6`V>~c0kgMJeJ45T9M!l`@M;Y3CGsfmgDN`T2U7G4Cw96n>QTPAxZ+@_!Hp&EBgSR9~v6U
z758+UKrc&6ORMn7z(&Wf%}bXq|H1Qtdr`+C=4>x7FOH6m4o6p4m*eE*RAIYgYrCxqLcp9ibFVSv3Q-Yc63DRdA2DT;-*If#WSci{-pu*<@uLvXuAN!I
z3lK8|yJbzn?{}{YbLY8p=c-*+CsYIdFF!xO!rluTBYZx%W@l$tJQv3QN6I8u#0b58
z`?ex3s7@weKOaDbM@*Hdx&VPcuWM0JQH5@B>((vK@#Dui`}XbQn46nd*a#rM!B&8H
zPdvwa*rMRu7gc`*4eZ>xvyKn2)D1Cb?%1)T!bZajhr&JwEddXHets3Wg{^_@m_$Cr
z^=#X=jdSJ7l?qz|#ipT?y34ixFx~AHX*lNU7ikc9!d*{xb3VzOZth4PK=o54ReFc6g
zHVHHk5fM=rBPaw9z?utD=H0Jfzj7{IxWEzQ8(@oXUio0Rym;|qg{;Vi20$zDLx6sG
zm09=v|I3Qtw~rn@5-Ju4{vCUJ`%3eAws-(89UL53$BRM7fS${?e3B15tg87KDZ4gb
z!2_7BoSIDh{9FT*{7A7Y3g53rR91@(*hJ~cI!1KpL>_a|Qww*kEk{8CUt>`isc
zdTe2hb|B_}O}hp4i}@ZpCu~)0+wwc-!`RQr$Y6rtU-yvpH*DA-5=;tTgM3s3aY@dpz`q^`~^M$#Ha{U4`NJV_pR!LKI`e}3Dp*1+Fcv+
z!Vd$xt)O)I@@1j)eBcCnl(2SX^%c11S0=xAz$5f_Va6Wj7`CA(v*Mi0<
z*4wgOZx6i;bGe{0>2T)u8}X#D&#;Z}LOwS8M{ui)+cU@$uyJ8elG=i=s%{7LTiCt$
zCBOmk)}R$O^;=q6R@pd&4u
zI^5a(M*Fa~hz%?eOO~0L$)?zfJOuBsL5XUAV$-hLng{Fe1?HzQ7i3z*9AeKwVQpHq6`#Vi3w_3TrLX(uh8x6)W1e7BHsV04
z+75>{VQ(-t^~08dbs_vxPEJmR-w5m8*_8RG<$=8qdNsx>WIsVR6Jf@`FnhT1!x8-*
z#{bEaCt2Z&jr=f0=%;^!ZU=b5
zb^*I6bZ9|xJ};O-|3_RH8~9^fVQ-$QOxSaPt!xfEg&@9$_=P`R-UGa_h5|9!g5-Na
zxB@)kTVZPlLrh>*#pJ;Dfb!VT9`axvgP?@iCAQ`LZuubFAwC0sddO{6m9Sp`Y{hKg
z0ouEN|GvO+D5!0qyW6*Kv#uAmM?rhYV&21^R&4t5JLZAE9s4p=b;2CL)&>N)!Crtp
z8bwXO6J%6j_MKv5%YbaaR+s%9@sBkUknyS`A#R%O901tC76)1sG#@kD3i|x8dXkj)4E!(LUw#uYN_`W@~u9$@3D4juqFLdUAi*(=~5^uNl$6zzb&UeMSFEU@NF
zSl(5cw*9Ja(MOz-Bq*L6xD+K}jy`?*^e>N#2c086pN*{nJ|AK9mtTdus;U?ETJY-X
zO0dhoXa1|!Mxb8IBW(Hz{R8p==%uRQTieUQJV*A?0Uv;m7dkw~3haUS!#IYV0J#V;
zKo}!{CmVeY{1oywbncp_0n~?eB5dRRv91ZaXl=(?Rkjbbjy)d1AF;LvadC+AhQA*&
zFywLY2-t{$L&P~khq5e>wS4j71#7l}^*pGjrgUoH9{UZj#XUL#Iu&)zT2@5EkW`R-ouB+)>i~RfS5_p7~A-8QQ-ht4{`^1lrXX__#a~2*~XBH+P**KJMa#~
z-9tBLn?NtvN1;0QsD6Y
z!khwoBg#VziXa_N5Us-g^tZp~6@>;Me?czDB
ztQ%r^MfIBq(-+i-I6}m9RMmW3RrnO89K<-NG=w<(^-@v_%
zjZK9O9{6VdG3S5uh5iRV0Dnhy@6idLT4mN4fS1EQ1iKvk(C{NACMH&_9f0i+dJbEe
z2D}n*fn3keb_AYZo5wx+fpHK23ls0;UJ(943xFfe$gEBpfbEXWo}pw+)33lc<|_E4
zF~U(f=LFmXHt=)T#&M4}ahvZ6-pQ2>{?SkH0oYx!
zCZIZa8Q>_2{D(1!zKDWjHvIq`;p@X1B=8p`)Cqa9w#I;AzGlk#1mDanTl|9taHb1r
zpgQ7SG4H~jE^NY_QQh%4paJkc*vC>*QYvCvfcx4y?&2C%lOs^kI055jN9HbLJ1TVn79(Jo{kemWj6{F6N?K|A0Z(071a
zVg9fu0AzPTZ4~q#bO^f)+XTDapS<=~5WL8H;GUOlhZo-Q9DD*aL*!=ouwnOyt|tus
zp%=hjg1MkF@(}2c?K(5)Ua-}{wn51Z@2f}_Gm=Bn=0Kd)OJoYi}h0*T`55Ty`7$f5z<-kV7
zYcFQx10N7YCX9@XtcdRsWsKq*)D3?e;(cM$#aaN!8L;(W-V&C!{*?TH4O_b&!8;lE
z;1~394?aL>f){+i2e3v)SRR1z6x_oO~j`O)3%z*3mCAm=hN|y
z-;fWm4+g$RTQTlI3q)=JPvF-F&J!NBR}x8$6!yd|WZkx!DQWjDONr!UsgL4}cFqZYA_c
z%B;I`rwNP|QRaK-c)%%vGx!I;a)iM@a0U4bd_Y(`A!I`A`-!&H@d55QCu4!=X57Xr
zeVj9YW88z!l5tPUVe)+Xcf#TyZA7`E>V}vLpwp2yl0Mg6|3ecP8=~m<823#6iaCHT
z>(TK}ev5*C;ELFYM9~c)L%_}h-c*P8|K$a+dBFZf@Wb|s@kozv#F}}me--q-sQ4!|
z03Wa@GyvUD6g%OcPA}k#7#oPM5QIDWdyI3sEf4cQ)+K^3(DN~Wi;91=6Y=w+$N{kB
zVGp6d)s`cOh5=jPMG)?oxWqh9p94Sxg31vE|7aihjVQQ>T_0=n>v;eF@_i;v5I(?9
zc4Oin_k<4+_zEgVSo~wm!v7|UJrH|=fhVC&%>LHh|C=5FC)n$RoeQ8hfDaHo3w!{2
z0XKdk4F1s`#9fFw?wLM_I-LI-=S-LY=Ay)SfCeBBkg*1xjhh{SE&eg?ac&~Uu(0yp
zvuDr#XI^6VvF@Hf9RP~G9Qt))Lr@G
zoCzO{U(kTCHX-DP4VlgdFc%QHLJq+Ojl9-eTe_Tp2|f2ByF#|Rt+rxH)Q;B!!@sGL^mXO0UzMDZxMJt#=R)GN8AtA
za*;afa9%YyXTp(;Ut#A0@B!$Cy!bN8#e6Rc&&S!Ch|yxUweG(9XaIab6qyh*ImSO7
zH_-7Q=Zhli)#1K+a7@P!x8E4AnAe5n1DFfI2S}MH2l~CJ;~su1QdZryW@&+!ZHJc}
zK%PT}#6B6AtD#$pGVXEyac$lA=x?G!j9=JxgyjR!0f2wlb%nL-MMOl1e16;Cgqxb`
zEBFBB0%7Cg36T{-_tgP;LH@dIq|58UI-
z!@qgm?e9ukpaFjI1A_36HDB0gr;g|U@7VgC=m9jqD}I0<{(*apd+gEvJN37&t^cM~
z=!V?l2YBHhxW91WLXGYJU5B%OSPWBQ6Z~
zf5h}-T`$uoT-(}R*Pg1QP0#@JI^bVNN9VUa$FPnjs*Wb=U|9#tIvS{>fjSzfqk%da
zsH1^88mL|xpz2Z`1nMAA2Z1^W)Ip#Q0)HI@`j+=tsr=8X{7;OMF8^Pilqf2^`G5W@
z?#uuEZgQBuzJ5jA0BnoDTiYw!UYrq!v&?Xw5%xJdckW!RJs-HTePwXH6S~7?5J3Kggqa4r8jTh)aw4DFQo7EJ`@%fR?q|X
zI|crb&&tY*6BHE0$;!&Az&GF}C?Te%Hsc@be)*;M@85IIo;_Q!K9o&=nPsJ>rq*iz
z;+i#UL^^+#*-w7=paHD6tgUo_Jvl|eZE0yKCqF;G;=Cq|7k*{nOee%6*T%U3@(K1T
zW0TNN>~n&BGQcB2KR8PZvLE;Z;^)Bgxg~sSYinC8=>YpTaFbt1KQJ$#-)zo#L)n86tAFMA0R1x0UBf+SUDS5r
z{B&+GK+GBTjDhTcy$3K)V6MSgU%!GrFu#MonaRh;N94W}8V4N+bH=%+r)Q0i59}Kb
zI;SV#f>%5!@QVFnaQ-Lud&8dNz#HI5`c1zgwv=tcegwSAp_f^ezt5jP|F7m@UgTB>
z&a8%B!%P?}SZB#Cej4MQ*Sx?i2YeXw3b(qe;~B;_>=pEcc^zl*G3&$GZi3G11q`_1
z5Be3G1Ujrq9snB0ney}m-o)g2=o8MN6qFzrZQHi(U$C>ZwB#!z;k&4)sQ>QG!GwKv
z-D7Ms7FSFg)D~U;GHK`Av-#B{%
zJVp>5zkU0btGw&x=Ef6d1TKIPw>85!|A(1s@+=U{!Aw5SY!A5ye7M=bFjoM6ymVdA
zH~l;gLIZ$3_RXOu%(2A2MDkVV6>Y#d&1@65F@W{~2A3{f;$&xMSMUSC0`mgwhP>&&=dNLxgPdVUUL`pMkemj2Arc(-Th^j5B;5&
zt(qHLV87*dRyea-qWlam7JR_nBEA@Pa*nc_oZx$gP+k
zfMX92kBYH_al&o<@G1vjmAMDby}Z0CY%%D6aBwgO
zd)bI$!$mt#maqwY4`(GozQ1N}(4-fw@@2KuRu`M6;OmIqQom>g8GwV$@Y#{isa2
z!oq;rf9&54y@T|Zenm_UXuh`goxqJP3@~2c+a=%e>pSE*`nf3No7#E>4A5S}1L#*W
z7LbSNc>MYfI|comz}nhpX1fR-(ECn)6P}1~Fy495Jo=8f17_L3%e^2NAZ7#l4Sk%G
z-=KNO^}kDBd9{-t40!4Pu)D&a!K=*Q?Kxn;O+Mh(f5h7SiRZNuI>6W`e1O@1_^6GI
zjsFsR&e;ZqavCHnx>UH?u9V4sM=<$qe`fB)SlqG#>fCjz_{vBZXkhQHJ=BI=kVYoFlf
zLF^9VphPXJroV$93bD-e1p8J^w}W0E=3KTu63`7ZK9F1dIKBMp{0;vO)`P-kz_g!{
zdO`1iJK}^88^=tDF(i3w@(LdwofZ&}g_sXw2Z9U?c@TLJhro=k1mH&KN&#umG*o#{g+NXa~N0*aNwJhi90-Kxg#+fBg8d#(iOk
zDW~&9#FHUTjtx%*Uqb8$y$^^#hkpdT7XA&aZA5G`oAP+Uir;hQdP?vd@JxQ+(BGk5
z@I~`Wh{uI}lm1;*{6Wf{TV4sVHFSFgXo${J(QeQjd=|otCpt{{{YLv>8z%{L
zLXUHT{gBRANIr4}zLwMGUC2lDeI-PRKjqh6@(%T2%_cMc95JbMcp@Kj4I*hfuFSCx
zc+l4{Ku;ibR>c*34(nrh@d@CYX|LurCXtu9o)SI*l7KgUbDt>v0d3HEC8>*kWv+7o
zJ}^${a0QKHj-by+pl`&XkW^iJi6QQbU&7ipCfv|A;03Z0)_XutV2($`Kw~_R#BEKq
zC@^P!gEO6gTk;1wz#l!q=Oaw4G58L~0!hFRWFuzXRdEk~v3vLKiv4o{Gw@`{jPO&^
z6V_CtU4rU_tsAkP^n~$M({XKBJILfmpkc^y+~Q54ce=W|R>aZM+fIJNk1MF}Y~O=c
zne@u-Tf`M{Tl0@+peg9N&;{T}=QppR50JkxA9Jfmm}iiUv6dRVj!hr1)|>6RUjl1h
zSI9_}iTOs`5l;@i4zWhy{cQRGx@WWY96SJXHs(Uar!y0HuBbkLz!7bSZ2;{DEHKU>
z>(gZfZn(sItodXn@JF;0^aJ{ajzZ>Z@CC@|(0hJ9q%z>C=i0(asUChZ50K_3v?
z%&!lS;kfPjg7)D%er>`$0htxJX10sXJ+tj}_>));T!C}?{7EkxG)vZ<5F9|(ya&zD{qbl!U=9AqEiMIXZRqkcDGzfObMFjM;YrFAbOqd*Z3lk_%+N-(
ziCZ6Vb~2%1QU~(;`ucKG%k5a;laQIX%>g8TWv|?525pD@3%#G{RJ{6t_0Zhp1<(O>
zZt&mAwvpHObUs7IE4}S_M%s@uc=Z9i3Os~YJ=O7C5ZpG4s__G4T?j$yVP
zx=Ur|d$#SS=L4)U{^)&xT^zO<(g%9`fj7uu%(kQ7HQjd75A=bF2YMe!`vG@uZHF$%
zZ5|-y*Tj_@Es;Ke4|0P$WC`#pezHVOw4Kz!4G*9TZfytsV9$C{=Xz3SRbRRFfiAxh
zx@Rj(S9SZ?l*gncdiy~$up{u3A=%VX-FfJIiL@U&z_DY;YJJ-YYzQr({g|t;2TyH>
zJ83()f|g)!f-i?WtGoXGv0jzIVR?8^UHXL(K%ACz`JYnx-+$w@TGmXQ7Gylk>9EyR
zr%uU>KIwb=!oR~SpQz8Vh6`&oxqT1)j&9dDbLI@!eB8ce^9(j``0(H}f?pD{5oA`_
z{9zk_-HM*7dM_L30Q7{I5N`HZk_Y~hs?>P_cW(YN*wZ1mgYKXs(rt~9$C!R(Hn8TE
z2YVNh1REgiC`>vBULc1M*uXYjRdOtJde~KwAlvh5C!WJUNc>u`7s6%>I~&%N^ZSn9
zJ94%TY)7O|ph3_E;Eq^7x;+N?U?$kkMA4^EAKAyBKDLiPkHCqOzes?QC@@ExAR99i_$(QBXd~>1uusAMPwIgzjkPvN
zh$Gx#>iBhP|_R
zCHOkw=b-zZ(LR3l;vK0Q{0#L2=fESkHW1n-Z2;Y4K7bFL@E?p@>|c!74?*!gfGhe<
zY;B}|v;n-H*#__clHe03b}VKeA(IJ;O+($VS&+K%8*v60Kd2vn%$Nw+{|Jqt-^_a1
z-qT@@`T+yL3NS>U=xso}3EGOXG48?BFc-jv#I`gG-~hiFy>7@&1SaIWs=PAW0NNn^2EQddr7G)WmPN+}
z;Xjx=$Xv_JUmf?P4X7V_4L9Fkb<|5Q6K#N9j_Et4=lR`#mzxKEX@Z@i+$>RHtN5>-
zqMqn>3Nl{_n(GMOtgWpp_7=i?0@(z74T3UVsuVd$b{jv{q&yFyPw
zqQ^>rufhh8vLVaTbtz^USn~iq49~&0&<3o3pzA!m;u4@YAchV49B7=#N#JqdxwywX
zz^oJZkV7EvAt8]` with older `FSharp.Core` package versions. ([PR #16373](https://github.com/dotnet/fsharp/pull/16373))
+* Parser recovers on unfinished `as` patterns. ([PR #16404](https://github.com/dotnet/fsharp/pull/16404))
+* Allow type-checking of unfinished object expressions. ([PR #16413](https://github.com/dotnet/fsharp/pull/16413))
+* Parser recovers on unfinished enum case declarations. ([PR #16401](https://github.com/dotnet/fsharp/pull/16401))
+* Parser recovers on unfinished record declarations. ([PR #16357](https://github.com/dotnet/fsharp/pull/16357))
+* `MutableKeyword` to [SynFieldTrivia](../reference/fsharp-compiler-syntaxtrivia-synfieldtrivia.html) ([PR #16357](https://github.com/dotnet/fsharp/pull/16357))
+* Added support for a new parameterless constructor for `CustomOperationAttribute`, which, when applied, will use method name as keyword for custom operation in computation expression builder. ([PR #16475](https://github.com/dotnet/fsharp/pull/16475), part of implementation for [fslang-suggestions/1250](https://github.com/fsharp/fslang-suggestions/issues/1250))
+* Compiler service API for getting ranges of unnecessary parentheses. ([PR #16079](https://github.com/dotnet/fsharp/pull/16079) et seq.)
+
+### Changed
+
+* Speed up unused opens handling for empty results. ([PR #16502](https://github.com/dotnet/fsharp/pull/16502))
diff --git a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md
new file mode 100644
index 00000000000..1c70a67edc6
--- /dev/null
+++ b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md
@@ -0,0 +1,19 @@
+### Fixed
+
+* Code generated files with > 64K methods and generated symbols crash when loaded. Use infered sequence points for debugging. ([Issue #16399](https://github.com/dotnet/fsharp/issues/16399), [#PR 16514](https://github.com/dotnet/fsharp/pull/16514))
+* `nameof Module` expressions and patterns are processed to link files in `--test:GraphBasedChecking`. ([PR #16550](https://github.com/dotnet/fsharp/pull/16550))
+
+### Added
+
+* Parser recovers on complex primary constructor patterns, better tree representation for primary constructor patterns. ([PR #16425](https://github.com/dotnet/fsharp/pull/16425))
+* Name resolution: keep type vars in subsequent checks ([PR #16456](https://github.com/dotnet/fsharp/pull/16456))
+* Higher-order-function-based API for working with the untyped abstract syntax tree. ([PR #16462](https://github.com/dotnet/fsharp/pull/16462))
+
+### Changed
+
+* Autogenerated .Is* members for unions skipped for single-case unions. ([PR 16571](https://github.com/dotnet/fsharp/pull/16571))
+* `implicitCtorSynPats` in `SynTypeDefnSimpleRepr.General` is now `SynPat option` instead of `SynSimplePats option`. ([PR #16425](https://github.com/dotnet/fsharp/pull/16425))
+* `SyntaxVisitorBase<'T>.VisitSimplePats` now takes `SynPat` instead of `SynSimplePat list`. ([PR #16425](https://github.com/dotnet/fsharp/pull/16425))
+* Reduce allocations in compiler checking via `ValueOption` usage ([PR #16323](https://github.com/dotnet/fsharp/pull/16323))
+* Reverted [#16348](https://github.com/dotnet/fsharp/pull/16348) `ThreadStatic` `CancellationToken` changes to improve test stability and prevent potential unwanted cancellations. ([PR #16536](https://github.com/dotnet/fsharp/pull/16536))
+* Refactored parenthesization API. ([PR #16461])(https://github.com/dotnet/fsharp/pull/16461))
diff --git a/docs/release-notes/.FSharp.Core/8.0.200.md b/docs/release-notes/.FSharp.Core/8.0.200.md
new file mode 100644
index 00000000000..8a1feafaf64
--- /dev/null
+++ b/docs/release-notes/.FSharp.Core/8.0.200.md
@@ -0,0 +1,4 @@
+### Added
+
+* More inlines for Result module. ([PR #16106](https://github.com/dotnet/fsharp/pull/16106))
+* Added a new parameterless constructor for `CustomOperationAttribute` ([PR #16475](https://github.com/dotnet/fsharp/pull/16475), part of implementation for [fslang-suggestions/1250](https://github.com/fsharp/fslang-suggestions/issues/1250))
diff --git a/docs/release-notes/.FSharp.Core/8.0.300.md b/docs/release-notes/.FSharp.Core/8.0.300.md
new file mode 100644
index 00000000000..9acf7d07635
--- /dev/null
+++ b/docs/release-notes/.FSharp.Core/8.0.300.md
@@ -0,0 +1,3 @@
+### Fixed
+
+* Preserve original stack traces in resumable state machines generated code if available. ([PR #16568](https://github.com/dotnet/fsharp/pull/16568))
\ No newline at end of file
diff --git a/docs/release-notes/.Language/8.0.md b/docs/release-notes/.Language/8.0.md
new file mode 100644
index 00000000000..ad829f0a6b9
--- /dev/null
+++ b/docs/release-notes/.Language/8.0.md
@@ -0,0 +1,3 @@
+### Added
+
+* `while!` ([Language suggestion #1038](https://github.com/fsharp/fslang-suggestions/issues/1038), [PR #14238](https://github.com/dotnet/fsharp/pull/14238))
\ No newline at end of file
diff --git a/docs/release-notes/.Language/preview.md b/docs/release-notes/.Language/preview.md
new file mode 100644
index 00000000000..0fce580b51e
--- /dev/null
+++ b/docs/release-notes/.Language/preview.md
@@ -0,0 +1,9 @@
+### Added
+
+* Better generic unmanaged structs handling. ([Language suggestion #692](https://github.com/fsharp/fslang-suggestions/issues/692), [PR #12154](https://github.com/dotnet/fsharp/pull/12154))
+* Bidirectional F#/C# interop for 'unmanaged' constraint. ([PR #12154](https://github.com/dotnet/fsharp/pull/12154))
+* Make `.Is*` discriminated union properties visible. ([Language suggestion #222](https://github.com/fsharp/fslang-suggestions/issues/222), [PR #16341](https://github.com/dotnet/fsharp/pull/16341))
+
+### Fixed
+
+* Allow extension methods without type attribute work for types from imported assemblies. ([PR #16368](https://github.com/dotnet/fsharp/pull/16368))
diff --git a/docs/release-notes/.VisualStudio/17.10.md b/docs/release-notes/.VisualStudio/17.10.md
new file mode 100644
index 00000000000..0045b1bd64b
--- /dev/null
+++ b/docs/release-notes/.VisualStudio/17.10.md
@@ -0,0 +1,7 @@
+### Fixed
+
+* Show signature help mid-pipeline in more scenarios. ([PR #16462](https://github.com/dotnet/fsharp/pull/16462))
+
+### Changed
+
+* Use refactored parenthesization API in unnecessary parentheses code fix. ([PR #16461])(https://github.com/dotnet/fsharp/pull/16461))
diff --git a/docs/release-notes/.VisualStudio/17.9.md b/docs/release-notes/.VisualStudio/17.9.md
new file mode 100644
index 00000000000..47d796020d5
--- /dev/null
+++ b/docs/release-notes/.VisualStudio/17.9.md
@@ -0,0 +1,3 @@
+### Added
+
+* Analyzer & code fix for removing unnecessary parentheses. ([PR #16079](https://github.com/dotnet/fsharp/pull/16079) et seq.)
diff --git a/docs/release-notes/.aux/Common.fsx b/docs/release-notes/.aux/Common.fsx
new file mode 100644
index 00000000000..a64026d2934
--- /dev/null
+++ b/docs/release-notes/.aux/Common.fsx
@@ -0,0 +1,50 @@
+#i "nuget: https://api.nuget.org/v3/index.json"
+#r "nuget: Markdig, 0.33.0"
+#r "nuget: FsHttp, 12.1.0"
+
+open System.IO
+open System.Xml.Linq
+open System.Text.RegularExpressions
+open FsHttp
+
+let versionProps = Path.Combine(__SOURCE_DIRECTORY__, "../../../eng/Versions.props")
+let versionPropsDoc = XDocument.Load(versionProps)
+
+/// Find all published versions of a package on NuGet
+let getAvailableNuGetVersions (packageName: string) : Set =
+    let packageName = packageName.ToLowerInvariant()
+
+    http { GET $"https://api.nuget.org/v3-flatcontainer/%s{packageName}/index.json" }
+    |> Request.send
+    |> Response.deserializeJson<{| versions: string array |}>
+    |> fun json -> Set.ofArray json.versions
+
+/// Try and find the publish date on NuGet
+let tryGetReleaseDate (packageName: string) (version: string) : string option =
+    let packageName = packageName.ToLowerInvariant()
+
+    http { GET $"https://api.nuget.org/v3/registration5-gz-semver2/%s{packageName}/%s{version}.json" }
+    |> Request.send
+    |> Response.deserializeJson<{| published: string |}>
+    |> fun json ->
+        if System.String.IsNullOrWhiteSpace json.published then
+            None
+        else
+            Some(json.published.Split('T').[0])
+
+/// In order for the heading to appear in the page content menu in fsdocs,
+/// they need to follow a specific HTML structure.
+let transformH3 (version: string) (input: string) : string =
+    let pattern = "

(.*?)

" + + let replacement = + $"

$1

" + + Regex.Replace(input, pattern, replacement) + +/// Process all MarkDown files from the given release folder +let processFolder (path: string) (processFile: string -> string) : string = + Directory.EnumerateFiles(path, "*.md") + |> Seq.sortByDescending Path.GetFileNameWithoutExtension + |> Seq.map processFile + |> String.concat "\n" diff --git a/docs/release-notes/About.md b/docs/release-notes/About.md new file mode 100644 index 00000000000..20e5138533c --- /dev/null +++ b/docs/release-notes/About.md @@ -0,0 +1,62 @@ +--- +category: Release Notes +categoryindex: 600 +index: 1 +title: About +--- + +# About + +The release notes for the [F\# language](./Language.md), [FSharp.Core](./FSharp.Core.md) and [FSharp.Compiler.Service](./FSharp.Compiler.Service.md) are based on the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format. +The target audience of these release notes are the respective end-users. + +## Writing a changelog entry + +In order to keep the change logs consistent the following format was proposed for each entry: + +```md +* . ([PR #16106](https://github.com/dotnet/fsharp/pull/16106)) +``` + +Some tips: + +* Use valid [Markdown](https://www.markdownguide.org/). +* Use `*` as bullet point symbol. We don't want to mix `*` and `-`. +* Start your description with a capital and end the sentence with a dot. +* **Always** include a link to your pull request before the closing `)`, `([PR #16106](https://github.com/dotnet/fsharp/pull/16106))`. +* Optionally, include a link to an issue on `dotnet/fsharp` use `Issue #number` before the link to the pull request. + +Example: + +```md +* Correctly handle assembly imports with public key token of 0 length. ([Issue #16359](https://github.com/dotnet/fsharp/issues/16359), [PR #16363](https://github.com/dotnet/fsharp/pull/16363)) +``` + +* Optionally, include a link to a language suggestion from `dotnet/fsharp` use `Language suggestion #number` before the link to the pull request. + +Example: + +```md +* `while!` ([Language suggestion #1038](https://github.com/fsharp/fslang-suggestions/issues/1038), [PR #14238](https://github.com/dotnet/fsharp/pull/14238)) +``` + +* Choose the right section for your type of change. (`## Added`, `## Changed`, `## Deprecated`, `## Removed`, `## Fixed` or `## Security`). +* Ensure your description makes it clear what the change is about. The reader should be informed on a high level without needing to click through the pull request link and find out in the code what actually changed. +* Maintainers or other contributors might rewrite your changelog entry in the future. This might be done when multiple pull requests can be consolidated under the same umbrella. +* Related pull requests can be listed in the same entry when it makes sense. + +Example: + +```md +* Miscellaneous fixes to parentheses analysis. ([PR #16262](https://github.com/dotnet/fsharp/pull/16262), [PR #16391](https://github.com/dotnet/fsharp/pull/16391), [PR #16370](https://github.com/dotnet/fsharp/pull/16370)) +``` + +## The release process + +### General + +How does it work? Different stages/phases? + +#### FSharp.Compiler.Service + +Perhaps add some specific info if available? \ No newline at end of file diff --git a/docs/release-notes/FSharp.Compiler.Service.fsx b/docs/release-notes/FSharp.Compiler.Service.fsx new file mode 100644 index 00000000000..fc116d572cf --- /dev/null +++ b/docs/release-notes/FSharp.Compiler.Service.fsx @@ -0,0 +1,47 @@ +(** --- +category: Release Notes +categoryindex: 600 +index: 4 +title: FSharp.Compiler.Service +--- + +# FSharp.Compiler.Service +*) +(*** hide ***) +#load "./.aux/Common.fsx" + +open System.IO +open System.Xml.XPath +open Markdig +open Common + +let path = Path.Combine(__SOURCE_DIRECTORY__, ".FSharp.Compiler.Service") +let fcsMajorVersion = versionPropsDoc.XPathSelectElement("//FCSMajorVersion").Value +let nugetPackage = "FSharp.Compiler.Service" +let availableNuGetVersions = getAvailableNuGetVersions nugetPackage + +processFolder path (fun file -> + let versionInFileName = Path.GetFileNameWithoutExtension(file) + // Example: 8.0.200 + let versionParts = versionInFileName.Split '.' + + let version = $"%s{fcsMajorVersion}.%s{versionParts.[0]}.%s{versionParts.[2]}" + // TODO: Can we determine if the current version is in code freeze based on the Version.props info? + let title = + if not (availableNuGetVersions.Contains version) then + $"%s{version} - Unreleased" + else + match tryGetReleaseDate nugetPackage version with + | None -> $"%s{version} - Unreleased" + | Some d -> $"%s{version} - %s{d}" + + let nugetBadge = + if not (availableNuGetVersions.Contains version) then + System.String.Empty + else + $"\"Nuget\"" + + let content = File.ReadAllText file |> Markdown.ToHtml |> transformH3 version + + $"""

%s{title}

%s{nugetBadge}%s{content}""") +(*** include-it-raw ***) diff --git a/docs/release-notes/FSharp.Compiler.Service/8.0.200.md b/docs/release-notes/FSharp.Compiler.Service/8.0.200.md deleted file mode 100644 index 53c6e8a4e67..00000000000 --- a/docs/release-notes/FSharp.Compiler.Service/8.0.200.md +++ /dev/null @@ -1,5 +0,0 @@ -- Parens analysis: miscellaneous fixes - https://github.com/dotnet/fsharp/pull/16262 -- Parens: Keep parentheses around non-struct tuples in `&` patterns - https://github.com/dotnet/fsharp/pull/16391 -- Parens analysis: fix some parenthesization corner-cases in record expressions - https://github.com/dotnet/fsharp/pull/16370 -- Fixes #16359 - correctly handle imports with 0 length public key tokens - https://github.com/dotnet/fsharp/pull/16363 -- Raise a new error when interfaces with auto properties are implemented on constructor-less types - https://github.com/dotnet/fsharp/pull/16352 \ No newline at end of file diff --git a/docs/release-notes/FSharp.Core.fsx b/docs/release-notes/FSharp.Core.fsx new file mode 100644 index 00000000000..521ef4f630c --- /dev/null +++ b/docs/release-notes/FSharp.Core.fsx @@ -0,0 +1,42 @@ +(** --- +category: Release Notes +categoryindex: 600 +index: 3 +title: FSharp.Core +--- + +# FSharp.Core +*) +(*** hide ***) +#load "./.aux/Common.fsx" + +open System.IO +open Markdig +open Common + +let path = Path.Combine(__SOURCE_DIRECTORY__, ".FSharp.Compiler.Service") +let nugetPackage = "FSharp.Core" +let availableNuGetVersions = getAvailableNuGetVersions nugetPackage + +processFolder path (fun file -> + let version = Path.GetFileNameWithoutExtension(file) + + // TODO: Can we determine if the current version is in code freeze based on the Version.props info? + let title = + if not (availableNuGetVersions.Contains version) then + $"%s{version} - Unreleased" + else + match tryGetReleaseDate nugetPackage version with + | None -> $"%s{version} - Unreleased" + | Some d -> $"%s{version} - %s{d}" + + let nugetBadge = + if not (availableNuGetVersions.Contains version) then + System.String.Empty + else + $"\"Nuget\"" + + let content = File.ReadAllText file |> Markdown.ToHtml |> transformH3 version + + $"""

%s{title}

%s{nugetBadge}%s{content}""") +(*** include-it-raw ***) diff --git a/docs/release-notes/FSharp.Core/8.0.200.md b/docs/release-notes/FSharp.Core/8.0.200.md deleted file mode 100644 index 8bed6454108..00000000000 --- a/docs/release-notes/FSharp.Core/8.0.200.md +++ /dev/null @@ -1 +0,0 @@ -- More inlines for Result module - https://github.com/dotnet/fsharp/pull/16106 \ No newline at end of file diff --git a/docs/release-notes/Language.fsx b/docs/release-notes/Language.fsx new file mode 100644 index 00000000000..73c173e7774 --- /dev/null +++ b/docs/release-notes/Language.fsx @@ -0,0 +1,35 @@ +(** --- +category: Release Notes +categoryindex: 600 +index: 2 +title: F# Language +--- + +# F\# Language +*) +(*** hide ***) +#load "./.aux/Common.fsx" + +open System.IO +open Markdig +open Common + +let path = Path.Combine(__SOURCE_DIRECTORY__, ".Language") + +Directory.EnumerateFiles(path, "*.md") +|> Seq.sortWith (fun a b -> + let a = Path.GetFileNameWithoutExtension a + let b = Path.GetFileNameWithoutExtension b + + match a, b with + | "preview", "preview" -> 0 + | "preview", _ -> -1 + | _, "preview" -> 1 + | _, _ -> compare (int b) (int a)) +|> Seq.map (fun file -> + let version = Path.GetFileNameWithoutExtension(file) + let version = if version = "preview" then "Preview" else version + let content = File.ReadAllText file |> Markdown.ToHtml |> transformH3 version + $"""

%s{version}

%s{content}""") +|> String.concat "\n" +(*** include-it-raw ***) diff --git a/docs/release-notes/Language/preview.md b/docs/release-notes/Language/preview.md deleted file mode 100644 index 7d9996a870e..00000000000 --- a/docs/release-notes/Language/preview.md +++ /dev/null @@ -1 +0,0 @@ -- Feature: Better unmanaged structs handling - https://github.com/dotnet/fsharp/pull/12154 \ No newline at end of file diff --git a/docs/running-documentation-locally.md b/docs/running-documentation-locally.md new file mode 100644 index 00000000000..ebecfd583b7 --- /dev/null +++ b/docs/running-documentation-locally.md @@ -0,0 +1,46 @@ +--- +title: Running the documentation locally +category: Compiler Internals +categoryindex: 200 +index: 999 +--- +# Running the documentation locally + +The source of this documentation website is hosted on https://github.com/fsharp/fsharp-compiler-docs. +You can follow this guide to see the results of your document changes rendered in the browser. + +## Setup + +`fsharp/fsharp-compiler-docs` will clone the `dotnet/fsharp` repository first to generate the documentation. +You can however, easily run the documentation locally and modify the `docs` from `dotnet/fsharp`. + +* Clone `fsharp/fsharp-compiler-docs` at the same level as your local `dotnet/fsharp` repository: + + + git clone https://github.com/fsharp/fsharp-compiler-docs.git + + +* Restore the `FSharp.Compiler.Service` project in `fsharp-compiler-docs`: + + + cd fsharp-compiler-docs/FSharp.Compiler.Service + dotnet restore + + +* Restore the local tools in `fsharp-compiler-docs`: + + + cd .. + dotnet tool restore + + +* Run the documentation tool using your `dotnet/fsharp` fork as input. + + + dotnet fsdocs watch --eval --sourcefolder ../fsharp/ --input ../fsharp/docs/ + + +## Release notes caveat + +The release notes pages from `docs/release-notes` are composed from the MarkDown files in subfolders. +Changing any of these files, won't regenerate the served webpage. Only the changes to the `.fsx` will trigger the tool. This is a known limitation. diff --git a/eng/SourceBuildPrebuiltBaseline.xml b/eng/SourceBuildPrebuiltBaseline.xml index a578272a848..18c94ed53e3 100644 --- a/eng/SourceBuildPrebuiltBaseline.xml +++ b/eng/SourceBuildPrebuiltBaseline.xml @@ -3,8 +3,6 @@ - - 8 0 - 200 + 300 0 @@ -29,7 +29,7 @@ $(FSMajorVersion)-$(FSMinorVersion)-$(FSBuildVersion) $(FSMajorVersion).$(FSMinorVersion).$(FSBuildVersion) $(FSMajorVersion).$(FSMinorVersion).0.0 - 7.0.0.0 + 8.0.0.0 43 @@ -41,7 +41,7 @@ $(FCSMajorVersion)$(FCSMinorVersion)$(FCSBuildVersion) - 7.0.0 + 8.0.100 $(FSCorePackageVersionValue)-$(PreReleaseVersionLabel).* @@ -58,7 +58,7 @@ 17 - 9 + 10 $(VSMajorVersion).0 $(VSMajorVersion).$(VSMinorVersion).0 $(VSAssemblyVersionPrefix).0 @@ -77,21 +77,6 @@ - - - $(RestoreSources); - https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json; - https://pkgs.dev.azure.com/azure-public/vside/_packaging/vssdk/nuget/v3/index.json; - https://pkgs.dev.azure.com/azure-public/vside/_packaging/vs-impl/nuget/v3/index.json; - https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json; - https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json; - https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json; - https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json; - https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8-transport/nuget/v3/index.json; - https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json; - https://pkgs.dev.azure.com/azure-public/vside/_packaging/vssdk-archived/nuget/v3/index.json; - https://pkgs.dev.azure.com/azure-public/vside/_packaging/vs-impl-archived/nuget/v3/index.json; - @@ -106,7 +91,7 @@ 6.0.0 4.5.0 - 4.6.0-2.23126.2 + 4.6.0-3.23329.3 17.7.25-preview 17.7.35338-preview.1 17.7.58-pre @@ -183,7 +168,7 @@ 1.0.0 1.1.33 - 0.13.2 + 0.13.10 2.16.5 4.3.0.0 1.0.31 @@ -207,12 +192,11 @@ 2.4.2 5.10.3 2.2.0 - 1.0.0-beta.23426.1 - 1.0.0-prerelease.23602.3 - 1.0.0-prerelease.23602.3 - 1.0.0-prerelease.23602.3 - 1.0.0-prerelease.23602.3 - 1.0.0-prerelease.23602.3 + 1.0.0-prerelease.23614.4 + 1.0.0-prerelease.23614.4 + 1.0.0-prerelease.23614.4 + 1.0.0-prerelease.23614.4 + 1.0.0-prerelease.23614.4 diff --git a/eng/common/darc-init.ps1 b/eng/common/darc-init.ps1 index 435e7641341..8fda30bdce2 100644 --- a/eng/common/darc-init.ps1 +++ b/eng/common/darc-init.ps1 @@ -1,6 +1,6 @@ param ( $darcVersion = $null, - $versionEndpoint = 'https://maestro-prod.westus2.cloudapp.azure.com/api/assets/darc-version?api-version=2019-01-16', + $versionEndpoint = 'https://maestro.dot.net/api/assets/darc-version?api-version=2019-01-16', $verbosity = 'minimal', $toolpath = $null ) diff --git a/eng/common/darc-init.sh b/eng/common/darc-init.sh index 84c1d0cc2e7..c305ae6bd77 100755 --- a/eng/common/darc-init.sh +++ b/eng/common/darc-init.sh @@ -2,7 +2,7 @@ source="${BASH_SOURCE[0]}" darcVersion='' -versionEndpoint='https://maestro-prod.westus2.cloudapp.azure.com/api/assets/darc-version?api-version=2019-01-16' +versionEndpoint='https://maestro.dot.net/api/assets/darc-version?api-version=2019-01-16' verbosity='minimal' while [[ $# > 0 ]]; do diff --git a/eng/common/post-build/add-build-to-channel.ps1 b/eng/common/post-build/add-build-to-channel.ps1 index de2d957922a..49938f0c89f 100644 --- a/eng/common/post-build/add-build-to-channel.ps1 +++ b/eng/common/post-build/add-build-to-channel.ps1 @@ -2,7 +2,7 @@ param( [Parameter(Mandatory=$true)][int] $BuildId, [Parameter(Mandatory=$true)][int] $ChannelId, [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, - [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro-prod.westus2.cloudapp.azure.com', + [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro.dot.net', [Parameter(Mandatory=$false)][string] $MaestroApiVersion = '2019-01-16' ) diff --git a/eng/common/post-build/publish-using-darc.ps1 b/eng/common/post-build/publish-using-darc.ps1 index 8508397d776..1e779fec4dd 100644 --- a/eng/common/post-build/publish-using-darc.ps1 +++ b/eng/common/post-build/publish-using-darc.ps1 @@ -3,7 +3,7 @@ param( [Parameter(Mandatory=$true)][int] $PublishingInfraVersion, [Parameter(Mandatory=$true)][string] $AzdoToken, [Parameter(Mandatory=$true)][string] $MaestroToken, - [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro-prod.westus2.cloudapp.azure.com', + [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro.dot.net', [Parameter(Mandatory=$true)][string] $WaitPublishingFinish, [Parameter(Mandatory=$false)][string] $ArtifactsPublishingAdditionalParameters, [Parameter(Mandatory=$false)][string] $SymbolPublishingAdditionalParameters diff --git a/eng/common/post-build/trigger-subscriptions.ps1 b/eng/common/post-build/trigger-subscriptions.ps1 index 55dea518ac5..ac9a95778fc 100644 --- a/eng/common/post-build/trigger-subscriptions.ps1 +++ b/eng/common/post-build/trigger-subscriptions.ps1 @@ -2,7 +2,7 @@ param( [Parameter(Mandatory=$true)][string] $SourceRepo, [Parameter(Mandatory=$true)][int] $ChannelId, [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, - [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro-prod.westus2.cloudapp.azure.com', + [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro.dot.net', [Parameter(Mandatory=$false)][string] $MaestroApiVersion = '2019-01-16' ) diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1 index 6c4ac6fec1a..73828dd30d3 100644 --- a/eng/common/sdk-task.ps1 +++ b/eng/common/sdk-task.ps1 @@ -64,7 +64,7 @@ try { $GlobalJson.tools | Add-Member -Name "vs" -Value (ConvertFrom-Json "{ `"version`": `"16.5`" }") -MemberType NoteProperty } if( -not ($GlobalJson.tools.PSObject.Properties.Name -match "xcopy-msbuild" )) { - $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.6.0-2" -MemberType NoteProperty + $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.8.1-2" -MemberType NoteProperty } if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index e20ee3a983c..e24ca2f46f9 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -136,7 +136,7 @@ jobs: condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - ${{ if and(eq(parameters.runAsPublic, 'false'), eq(variables['System.TeamProject'], 'internal')) }}: - - task: NuGetAuthenticate@0 + - task: NuGetAuthenticate@1 - ${{ if and(ne(parameters.artifacts.download, 'false'), ne(parameters.artifacts.download, '')) }}: - task: DownloadPipelineArtifact@2 diff --git a/eng/common/templates/job/publish-build-assets.yml b/eng/common/templates/job/publish-build-assets.yml index 42017109f37..fa5446c093d 100644 --- a/eng/common/templates/job/publish-build-assets.yml +++ b/eng/common/templates/job/publish-build-assets.yml @@ -72,7 +72,7 @@ jobs: condition: ${{ parameters.condition }} continueOnError: ${{ parameters.continueOnError }} - - task: NuGetAuthenticate@0 + - task: NuGetAuthenticate@1 - task: PowerShell@2 displayName: Publish Build Assets @@ -81,7 +81,7 @@ jobs: arguments: -task PublishBuildAssets -restore -msbuildEngine dotnet /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' /p:BuildAssetRegistryToken=$(MaestroAccessToken) - /p:MaestroApiEndpoint=https://maestro-prod.westus2.cloudapp.azure.com + /p:MaestroApiEndpoint=https://maestro.dot.net /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} /p:OfficialBuildId=$(Build.BuildNumber) condition: ${{ parameters.condition }} diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index c24193acfc9..173914f2364 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -7,7 +7,7 @@ variables: # Default Maestro++ API Endpoint and API Version - name: MaestroApiEndPoint - value: "https://maestro-prod.westus2.cloudapp.azure.com" + value: "https://maestro.dot.net" - name: MaestroApiAccessToken value: $(MaestroAccessToken) - name: MaestroApiVersion diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index ef720f9d781..3f74abf7ce0 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -169,7 +169,7 @@ stages: # This is necessary whenever we want to publish/restore to an AzDO private feed # Since sdk-task.ps1 tries to restore packages we need to do this authentication here # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@0 + - task: NuGetAuthenticate@1 displayName: 'Authenticate to AzDO Feeds' # Signing validation will optionally work with the buildmanifest file which is downloaded from @@ -266,7 +266,7 @@ stages: BARBuildId: ${{ parameters.BARBuildId }} PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - task: NuGetAuthenticate@0 + - task: NuGetAuthenticate@1 - task: PowerShell@2 displayName: Publish Using Darc diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index aa74ab4a81e..eb188cfda41 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -379,13 +379,13 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = } # Minimum VS version to require. - $vsMinVersionReqdStr = '17.6' + $vsMinVersionReqdStr = '17.7' $vsMinVersionReqd = [Version]::new($vsMinVersionReqdStr) # If the version of msbuild is going to be xcopied, # use this version. Version matches a package here: - # https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-eng/NuGet/RoslynTools.MSBuild/versions/17.6.0-2 - $defaultXCopyMSBuildVersion = '17.6.0-2' + # https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-eng/NuGet/RoslynTools.MSBuild/versions/17.8.1-2 + $defaultXCopyMSBuildVersion = '17.8.1-2' if (!$vsRequirements) { if (Get-Member -InputObject $GlobalJson.tools -Name 'vs') { @@ -601,7 +601,15 @@ function InitializeBuildTool() { ExitWithExitCode 1 } $dotnetPath = Join-Path $dotnetRoot (GetExecutableFileName 'dotnet') - $buildTool = @{ Path = $dotnetPath; Command = 'msbuild'; Tool = 'dotnet'; Framework = 'net8.0' } + + # Use override if it exists - commonly set by source-build + if ($null -eq $env:_OverrideArcadeInitializeBuildToolFramework) { + $initializeBuildToolFramework="net8.0" + } else { + $initializeBuildToolFramework=$env:_OverrideArcadeInitializeBuildToolFramework + } + + $buildTool = @{ Path = $dotnetPath; Command = 'msbuild'; Tool = 'dotnet'; Framework = $initializeBuildToolFramework } } elseif ($msbuildEngine -eq "vs") { try { $msbuildPath = InitializeVisualStudioMSBuild -install:$restore diff --git a/eng/common/tools.sh b/eng/common/tools.sh index e8d47894334..3392e3a9992 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -341,7 +341,12 @@ function InitializeBuildTool { # return values _InitializeBuildTool="$_InitializeDotNetCli/dotnet" _InitializeBuildToolCommand="msbuild" - _InitializeBuildToolFramework="net8.0" + # use override if it exists - commonly set by source-build + if [[ "${_OverrideArcadeInitializeBuildToolFramework:-x}" == "x" ]]; then + _InitializeBuildToolFramework="net8.0" + else + _InitializeBuildToolFramework="${_OverrideArcadeInitializeBuildToolFramework}" + fi } # Set RestoreNoCache as a workaround for https://github.com/NuGet/Home/issues/3116 diff --git a/eng/restore-internal-tools.yml b/eng/restore-internal-tools.yml index f71d0710e44..01cd835c5b7 100644 --- a/eng/restore-internal-tools.yml +++ b/eng/restore-internal-tools.yml @@ -1,5 +1,5 @@ steps: - - task: NuGetAuthenticate@0 + - task: NuGetAuthenticate@1 inputs: nuGetServiceConnections: 'devdiv/dotnet-core-internal-tooling' forceReinstallCredentialProvider: true @@ -10,4 +10,4 @@ steps: /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/RestoreInternal.binlog /v:normal displayName: Restore internal tools - condition: and(succeeded(), ne(variables['_skipRestoreInternalTools'], 'true')) \ No newline at end of file + condition: and(succeeded(), ne(variables['_skipRestoreInternalTools'], 'true')) diff --git a/global.json b/global.json index 365652e8f7e..b5234bc1761 100644 --- a/global.json +++ b/global.json @@ -1,23 +1,23 @@ { "sdk": { - "version": "8.0.100-rc.1.23463.5", + "version": "8.0.101", "allowPrerelease": true }, "tools": { - "dotnet": "8.0.100-rc.1.23463.5", + "dotnet": "8.0.101", "vs": { - "version": "17.6", + "version": "17.8", "components": [ "Microsoft.VisualStudio.Component.FSharp" ] }, - "xcopy-msbuild": "17.7.2" + "xcopy-msbuild": "17.8.1-2" }, "native-tools": { "perl": "5.38.0.1" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.23463.1", + "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24060.4", "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23255.2" } } diff --git a/src/Compiler/AbstractIL/il.fs b/src/Compiler/AbstractIL/il.fs index be994a0307c..3b7df226c9f 100644 --- a/src/Compiler/AbstractIL/il.fs +++ b/src/Compiler/AbstractIL/il.fs @@ -805,7 +805,7 @@ type ILTypeRef = member tref.AddQualifiedNameExtension basic = let sco = tref.Scope.QualifiedName - if sco = "" then + if String.IsNullOrEmpty(sco) then basic else String.concat ", " [ basic; sco ] diff --git a/src/Compiler/AbstractIL/ilwrite.fs b/src/Compiler/AbstractIL/ilwrite.fs index cd4e1bfe721..f41c8aaa08d 100644 --- a/src/Compiler/AbstractIL/ilwrite.fs +++ b/src/Compiler/AbstractIL/ilwrite.fs @@ -50,6 +50,13 @@ let emitBytesViaBuffer f = use bb = ByteBuffer.Create EmitBytesViaBufferCapacity /// Alignment and padding let align alignment n = ((n + alignment - 1) / alignment) * alignment + +/// Maximum number of methods in a dotnet type +/// This differs from the spec and file formats slightly which suggests 0xfffe is the maximum +/// this value was identified empirically. +[] +let maximumMethodsPerDotNetType = 0xfff0 + //--------------------------------------------------------------------- // Concrete token representations etc. used in PE files //--------------------------------------------------------------------- @@ -652,7 +659,7 @@ let GetBytesAsBlobIdx cenv (bytes: byte[]) = else cenv.blobs.FindOrAddSharedEntry bytes let GetStringHeapIdx cenv s = - if s = "" then 0 + if String.IsNullOrEmpty(s) then 0 else cenv.strings.FindOrAddSharedEntry s let GetGuidIdx cenv info = cenv.guids.FindOrAddSharedEntry info @@ -672,8 +679,14 @@ let GetTypeNameAsElemPair cenv n = //===================================================================== let rec GenTypeDefPass1 enc cenv (tdef: ILTypeDef) = - ignore (cenv.typeDefs.AddUniqueEntry "type index" (fun (TdKey (_, n)) -> n) (TdKey (enc, tdef.Name))) - GenTypeDefsPass1 (enc@[tdef.Name]) cenv (tdef.NestedTypes.AsList()) + ignore (cenv.typeDefs.AddUniqueEntry "type index" (fun (TdKey (_, n)) -> n) (TdKey (enc, tdef.Name))) + + // Verify that the typedef contains fewer than maximumMethodsPerDotNetType + let count = tdef.Methods.AsArray().Length + if count > maximumMethodsPerDotNetType then + errorR(Error(FSComp.SR.tooManyMethodsInDotNetTypeWritingAssembly (tdef.Name, count, maximumMethodsPerDotNetType), rangeStartup)) + + GenTypeDefsPass1 (enc@[tdef.Name]) cenv (tdef.NestedTypes.AsList()) and GenTypeDefsPass1 enc cenv tdefs = List.iter (GenTypeDefPass1 enc cenv) tdefs @@ -682,7 +695,8 @@ and GenTypeDefsPass1 enc cenv tdefs = List.iter (GenTypeDefPass1 enc cenv) tdefs //===================================================================== let rec GetIdxForTypeDef cenv key = - try cenv.typeDefs.GetTableEntry key + try + cenv.typeDefs.GetTableEntry key with :? KeyNotFoundException -> let (TdKey (enc, n) ) = key diff --git a/src/Compiler/Checking/AttributeChecking.fs b/src/Compiler/Checking/AttributeChecking.fs index 977d0ecccc6..79dc9402014 100644 --- a/src/Compiler/Checking/AttributeChecking.fs +++ b/src/Compiler/Checking/AttributeChecking.fs @@ -210,7 +210,7 @@ let TryBindMethInfoAttribute g (m: range) (AttribInfo(atref, _) as attribSpec) m (fun provAttribs -> match provAttribs.PUntaint((fun a -> a.GetAttributeConstructorArgs(provAttribs.TypeProvider.PUntaintNoFailure(id), atref.FullName)), m) with | Some args -> f3 args - | None -> None) + | None -> None) #else (fun _provAttribs -> None) #endif diff --git a/src/Compiler/Checking/CheckComputationExpressions.fs b/src/Compiler/Checking/CheckComputationExpressions.fs index 26b10550394..f0727c3fc5d 100644 --- a/src/Compiler/Checking/CheckComputationExpressions.fs +++ b/src/Compiler/Checking/CheckComputationExpressions.fs @@ -1,6 +1,6 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. -/// The typechecker. Left-to-right constrained type checking +/// The typechecker. Left-to-right constrained type checking /// with generalization at appropriate points. module internal FSharp.Compiler.CheckComputationExpressions @@ -28,65 +28,91 @@ open FSharp.Compiler.TypedTreeOps type cenv = TcFileState /// Used to flag if this is the first or a sebsequent translation pass through a computation expression -type CompExprTranslationPass = Initial | Subsequent +type CompExprTranslationPass = + | Initial + | Subsequent /// Used to flag if computation expression custom operations are allowed in a given context -type CustomOperationsMode = Allowed | Denied +type CustomOperationsMode = + | Allowed + | Denied -let TryFindIntrinsicOrExtensionMethInfo collectionSettings (cenv: cenv) (env: TcEnv) m ad nm ty = +let TryFindIntrinsicOrExtensionMethInfo collectionSettings (cenv: cenv) (env: TcEnv) m ad nm ty = AllMethInfosOfTypeInScope collectionSettings cenv.infoReader env.NameEnv (Some nm) ad IgnoreOverrides m ty /// Ignores an attribute let IgnoreAttribute _ = None -let (|ExprAsPat|_|) (f: SynExpr) = - match f with - | SingleIdent v1 | SynExprParen(SingleIdent v1, _, _, _) -> Some (mkSynPatVar None v1) - | SynExprParen(SynExpr.Tuple (false, elems, commas, _), _, _, _) -> - let elems = elems |> List.map (|SingleIdent|_|) - if elems |> List.forall (fun x -> x.IsSome) then - Some (SynPat.Tuple(false, (elems |> List.map (fun x -> mkSynPatVar None x.Value)), commas, f.Range)) +[] +let (|ExprAsPat|_|) (f: SynExpr) = + match f with + | SingleIdent v1 + | SynExprParen(SingleIdent v1, _, _, _) -> ValueSome(mkSynPatVar None v1) + | SynExprParen(SynExpr.Tuple(false, elems, commas, _), _, _, _) -> + let elems = elems |> List.map (|SingleIdent|_|) + + if elems |> List.forall (fun x -> x.IsSome) then + ValueSome(SynPat.Tuple(false, (elems |> List.map (fun x -> mkSynPatVar None x.Value)), commas, f.Range)) else - None - | _ -> None + ValueNone + | _ -> ValueNone -// For join clauses that join on nullable, we syntactically insert the creation of nullable values on the appropriate side of the condition, +// For join clauses that join on nullable, we syntactically insert the creation of nullable values on the appropriate side of the condition, // then pull the syntax apart again -let (|JoinRelation|_|) cenv env (expr: SynExpr) = +[] +let (|JoinRelation|_|) cenv env (expr: SynExpr) = let m = expr.Range let ad = env.eAccessRights let isOpName opName vref s = - (s = opName) && - match ResolveExprLongIdent cenv.tcSink cenv.nameResolver m ad env.eNameResEnv TypeNameResolutionInfo.Default [ident(opName, m)] None with - | Result (_, Item.Value vref2, []) -> valRefEq cenv.g vref vref2 - | _ -> false + (s = opName) + && match + ResolveExprLongIdent + cenv.tcSink + cenv.nameResolver + m + ad + env.eNameResEnv + TypeNameResolutionInfo.Default + [ ident (opName, m) ] + None + with + | Result(_, Item.Value vref2, []) -> valRefEq cenv.g vref vref2 + | _ -> false + + match expr with + | BinOpExpr(opId, a, b) when isOpName opNameEquals cenv.g.equals_operator_vref opId.idText -> ValueSome(a, b) - match expr with - | BinOpExpr(opId, a, b) when isOpName opNameEquals cenv.g.equals_operator_vref opId.idText -> Some (a, b) + | BinOpExpr(opId, a, b) when isOpName opNameEqualsNullable cenv.g.equals_nullable_operator_vref opId.idText -> - | BinOpExpr(opId, a, b) when isOpName opNameEqualsNullable cenv.g.equals_nullable_operator_vref opId.idText -> + let a = + SynExpr.App(ExprAtomicFlag.Atomic, false, mkSynLidGet a.Range [ MangledGlobalName; "System" ] "Nullable", a, a.Range) - let a = SynExpr.App (ExprAtomicFlag.Atomic, false, mkSynLidGet a.Range [MangledGlobalName;"System"] "Nullable", a, a.Range) - Some (a, b) + ValueSome(a, b) - | BinOpExpr(opId, a, b) when isOpName opNameNullableEquals cenv.g.nullable_equals_operator_vref opId.idText -> + | BinOpExpr(opId, a, b) when isOpName opNameNullableEquals cenv.g.nullable_equals_operator_vref opId.idText -> - let b = SynExpr.App (ExprAtomicFlag.Atomic, false, mkSynLidGet b.Range [MangledGlobalName;"System"] "Nullable", b, b.Range) - Some (a, b) + let b = + SynExpr.App(ExprAtomicFlag.Atomic, false, mkSynLidGet b.Range [ MangledGlobalName; "System" ] "Nullable", b, b.Range) - | BinOpExpr(opId, a, b) when isOpName opNameNullableEqualsNullable cenv.g.nullable_equals_nullable_operator_vref opId.idText -> + ValueSome(a, b) - Some (a, b) + | BinOpExpr(opId, a, b) when isOpName opNameNullableEqualsNullable cenv.g.nullable_equals_nullable_operator_vref opId.idText -> - | _ -> None + ValueSome(a, b) + + | _ -> ValueNone let elimFastIntegerForLoop (spFor, spTo, id, start: SynExpr, dir, finish: SynExpr, innerExpr, m: range) = let mOp = (unionRanges start.Range finish.Range).MakeSynthetic() - let pseudoEnumExpr = - if dir then mkSynInfix mOp start ".." finish - else mkSynTrifix mOp ".. .." start (SynExpr.Const (SynConst.Int32 -1, mOp)) finish - SynExpr.ForEach (spFor, spTo, SeqExprOnly false, true, mkSynPatVar None id, pseudoEnumExpr, innerExpr, m) + + let pseudoEnumExpr = + if dir then + mkSynInfix mOp start ".." finish + else + mkSynTrifix mOp ".. .." start (SynExpr.Const(SynConst.Int32 -1, mOp)) finish + + SynExpr.ForEach(spFor, spTo, SeqExprOnly false, true, mkSynPatVar None id, pseudoEnumExpr, innerExpr, m) /// Check if a computation or sequence expression is syntactically free of 'yield' (though not yield!) let YieldFree (cenv: cenv) expr = @@ -95,30 +121,27 @@ let YieldFree (cenv: cenv) expr = // Implement yield free logic for F# Language including the LanguageFeature.ImplicitYield let rec YieldFree expr = match expr with - | SynExpr.Sequential (expr1=expr1; expr2=expr2) -> - YieldFree expr1 && YieldFree expr2 + | SynExpr.Sequential(expr1 = expr1; expr2 = expr2) -> YieldFree expr1 && YieldFree expr2 - | SynExpr.IfThenElse (thenExpr=thenExpr; elseExpr=elseExprOpt) -> - YieldFree thenExpr && Option.forall YieldFree elseExprOpt + | SynExpr.IfThenElse(thenExpr = thenExpr; elseExpr = elseExprOpt) -> YieldFree thenExpr && Option.forall YieldFree elseExprOpt - | SynExpr.TryWith (tryExpr=body; withCases=clauses) -> - YieldFree body && clauses |> List.forall (fun (SynMatchClause(resultExpr = res)) -> YieldFree res) + | SynExpr.TryWith(tryExpr = body; withCases = clauses) -> + YieldFree body + && clauses |> List.forall (fun (SynMatchClause(resultExpr = res)) -> YieldFree res) - | SynExpr.Match (clauses=clauses) | SynExpr.MatchBang (clauses=clauses) -> - clauses |> List.forall (fun (SynMatchClause(resultExpr = res)) -> YieldFree res) + | SynExpr.Match(clauses = clauses) + | SynExpr.MatchBang(clauses = clauses) -> clauses |> List.forall (fun (SynMatchClause(resultExpr = res)) -> YieldFree res) - | SynExpr.For (doBody=body) - | SynExpr.TryFinally (tryExpr=body) - | SynExpr.LetOrUse (body=body) - | SynExpr.While (doExpr=body) - | SynExpr.WhileBang (doExpr=body) - | SynExpr.ForEach (bodyExpr=body) -> - YieldFree body + | SynExpr.For(doBody = body) + | SynExpr.TryFinally(tryExpr = body) + | SynExpr.LetOrUse(body = body) + | SynExpr.While(doExpr = body) + | SynExpr.WhileBang(doExpr = body) + | SynExpr.ForEach(bodyExpr = body) -> YieldFree body - | SynExpr.LetOrUseBang(body=body) -> - YieldFree body + | SynExpr.LetOrUseBang(body = body) -> YieldFree body - | SynExpr.YieldOrReturn(flags=(true, _)) -> false + | SynExpr.YieldOrReturn(flags = (true, _)) -> false | _ -> true @@ -127,25 +150,23 @@ let YieldFree (cenv: cenv) expr = // Implement yield free logic for F# Language without the LanguageFeature.ImplicitYield let rec YieldFree expr = match expr with - | SynExpr.Sequential (expr1=expr1; expr2=expr2) -> - YieldFree expr1 && YieldFree expr2 + | SynExpr.Sequential(expr1 = expr1; expr2 = expr2) -> YieldFree expr1 && YieldFree expr2 - | SynExpr.IfThenElse (thenExpr=thenExpr; elseExpr=elseExprOpt) -> - YieldFree thenExpr && Option.forall YieldFree elseExprOpt + | SynExpr.IfThenElse(thenExpr = thenExpr; elseExpr = elseExprOpt) -> YieldFree thenExpr && Option.forall YieldFree elseExprOpt - | SynExpr.TryWith (tryExpr=e1; withCases=clauses) -> - YieldFree e1 && clauses |> List.forall (fun (SynMatchClause(resultExpr = res)) -> YieldFree res) + | SynExpr.TryWith(tryExpr = e1; withCases = clauses) -> + YieldFree e1 + && clauses |> List.forall (fun (SynMatchClause(resultExpr = res)) -> YieldFree res) - | SynExpr.Match (clauses=clauses) | SynExpr.MatchBang (clauses=clauses) -> - clauses |> List.forall (fun (SynMatchClause(resultExpr = res)) -> YieldFree res) + | SynExpr.Match(clauses = clauses) + | SynExpr.MatchBang(clauses = clauses) -> clauses |> List.forall (fun (SynMatchClause(resultExpr = res)) -> YieldFree res) - | SynExpr.For (doBody=body) - | SynExpr.TryFinally (tryExpr=body) - | SynExpr.LetOrUse (body=body) - | SynExpr.While (doExpr=body) - | SynExpr.WhileBang (doExpr=body) - | SynExpr.ForEach (bodyExpr=body) -> - YieldFree body + | SynExpr.For(doBody = body) + | SynExpr.TryFinally(tryExpr = body) + | SynExpr.LetOrUse(body = body) + | SynExpr.While(doExpr = body) + | SynExpr.WhileBang(doExpr = body) + | SynExpr.ForEach(bodyExpr = body) -> YieldFree body | SynExpr.LetOrUseBang _ | SynExpr.YieldOrReturnFrom _ @@ -157,44 +178,43 @@ let YieldFree (cenv: cenv) expr = YieldFree expr - /// Determine if a syntactic expression inside 'seq { ... }' or '[...]' counts as a "simple sequence /// of semicolon separated values". For example [1;2;3]. /// 'acceptDeprecated' is true for the '[ ... ]' case, where we allow the syntax '[ if g then t else e ]' but ask it to be parenthesized -/// -let (|SimpleSemicolonSequence|_|) cenv acceptDeprecated cexpr = +[] +let (|SimpleSemicolonSequence|_|) cenv acceptDeprecated cexpr = - let IsSimpleSemicolonSequenceElement expr = + let IsSimpleSemicolonSequenceElement expr = match expr with | SynExpr.IfThenElse _ when acceptDeprecated && YieldFree cenv expr -> true | SynExpr.IfThenElse _ - | SynExpr.TryWith _ - | SynExpr.Match _ - | SynExpr.For _ - | SynExpr.ForEach _ - | SynExpr.TryFinally _ - | SynExpr.YieldOrReturnFrom _ - | SynExpr.YieldOrReturn _ - | SynExpr.LetOrUse _ - | SynExpr.Do _ - | SynExpr.MatchBang _ - | SynExpr.LetOrUseBang _ + | SynExpr.TryWith _ + | SynExpr.Match _ + | SynExpr.For _ + | SynExpr.ForEach _ + | SynExpr.TryFinally _ + | SynExpr.YieldOrReturnFrom _ + | SynExpr.YieldOrReturn _ + | SynExpr.LetOrUse _ + | SynExpr.Do _ + | SynExpr.MatchBang _ + | SynExpr.LetOrUseBang _ | SynExpr.While _ | SynExpr.WhileBang _ -> false | _ -> true - let rec TryGetSimpleSemicolonSequenceOfComprehension expr acc = - match expr with - | SynExpr.Sequential (_, true, e1, e2, _) -> - if IsSimpleSemicolonSequenceElement e1 then + let rec TryGetSimpleSemicolonSequenceOfComprehension expr acc = + match expr with + | SynExpr.Sequential(_, true, e1, e2, _) -> + if IsSimpleSemicolonSequenceElement e1 then TryGetSimpleSemicolonSequenceOfComprehension e2 (e1 :: acc) else - None - | _ -> - if IsSimpleSemicolonSequenceElement expr then - Some(List.rev (expr :: acc)) - else - None + ValueNone + | _ -> + if IsSimpleSemicolonSequenceElement expr then + ValueSome(List.rev (expr :: acc)) + else + ValueNone TryGetSimpleSemicolonSequenceOfComprehension cexpr [] @@ -202,112 +222,162 @@ let RecordNameAndTypeResolutions cenv env tpenv expr = // This function is motivated by cases like // query { for ... join(for x in f(). } // where there is incomplete code in a query, and we are current just dropping a piece of the AST on the floor (above, the bit inside the 'join'). - // + // // The problem with dropping the AST on the floor is that we get no captured resolutions, which means no Intellisense/QuickInfo/ParamHelp. // // We check this AST-fragment, to get resolutions captured. // // This may have effects from typechecking, producing side-effects on the typecheck environment. - suppressErrorReporting (fun () -> + suppressErrorReporting (fun () -> try - ignore(TcExprOfUnknownType cenv env tpenv expr) + ignore (TcExprOfUnknownType cenv env tpenv expr) with _ -> ()) /// Used for all computation expressions except sequence expressions -let TcComputationExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (mWhole, interpExpr: Expr, builderTy, comp: SynExpr) = +let TcComputationExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (mWhole, interpExpr: Expr, builderTy, comp: SynExpr) = let overallTy = overallTy.Commit - + let g = cenv.g let ad = env.eAccessRights let mkSynDelay2 (e: SynExpr) = mkSynDelay (e.Range.MakeSynthetic()) e - + let builderValName = CompilerGeneratedName "builder" let mBuilderVal = interpExpr.Range - + // Give bespoke error messages for the FSharp.Core "query" builder - let isQuery = - match stripDebugPoints interpExpr with + let isQuery = + match stripDebugPoints interpExpr with // An unparameterized custom builder, e.g., `query`, `async`. - | Expr.Val (vref, _, m) + | Expr.Val(vref, _, m) // A parameterized custom builder, e.g., `builder<…>`, `builder ()`. - | Expr.App (funcExpr = Expr.Val (vref, _, m)) -> - let item = Item.CustomBuilder (vref.DisplayName, vref) + | Expr.App(funcExpr = Expr.Val(vref, _, m)) -> + let item = Item.CustomBuilder(vref.DisplayName, vref) CallNameResolutionSink cenv.tcSink (m, env.NameEnv, item, emptyTyparInst, ItemOccurence.Use, env.eAccessRights) - valRefEq cenv.g vref cenv.g.query_value_vref + valRefEq cenv.g vref cenv.g.query_value_vref | _ -> false /// Make a builder.Method(...) call - let mkSynCall nm (m: range) args = + let mkSynCall nm (m: range) args = let m = m.MakeSynthetic() // Mark as synthetic so the language service won't pick it up. - let args = - match args with - | [] -> SynExpr.Const (SynConst.Unit, m) - | [arg] -> SynExpr.Paren (SynExpr.Paren (arg, range0, None, m), range0, None, m) - | args -> SynExpr.Paren (SynExpr.Tuple (false, args, [], m), range0, None, m) - + + let args = + match args with + | [] -> SynExpr.Const(SynConst.Unit, m) + | [ arg ] -> SynExpr.Paren(SynExpr.Paren(arg, range0, None, m), range0, None, m) + | args -> SynExpr.Paren(SynExpr.Tuple(false, args, [], m), range0, None, m) + let builderVal = mkSynIdGet m builderValName - mkSynApp1 (SynExpr.DotGet (builderVal, range0, SynLongIdent([mkSynId m nm], [], [None]), m)) args m + mkSynApp1 (SynExpr.DotGet(builderVal, range0, SynLongIdent([ mkSynId m nm ], [], [ None ]), m)) args m - let hasMethInfo nm = TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBuilderVal ad nm builderTy |> isNil |> not + let hasMethInfo nm = + TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBuilderVal ad nm builderTy + |> isNil + |> not - let sourceMethInfo = TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBuilderVal ad "Source" builderTy + let sourceMethInfo = + TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBuilderVal ad "Source" builderTy // Optionally wrap sources of "let!", "yield!", "use!" in "query.Source" - let mkSourceExpr callExpr = - match sourceMethInfo with + let mkSourceExpr callExpr = + match sourceMethInfo with | [] -> callExpr - | _ -> mkSynCall "Source" callExpr.Range [callExpr] + | _ -> mkSynCall "Source" callExpr.Range [ callExpr ] - let mkSourceExprConditional isFromSource callExpr = + let mkSourceExprConditional isFromSource callExpr = if isFromSource then mkSourceExpr callExpr else callExpr /// Decide if the builder is an auto-quote builder let isAutoQuote = hasMethInfo "Quote" - let customOperationMethods = - AllMethInfosOfTypeInScope ResultCollectionSettings.AllResults cenv.infoReader env.NameEnv None ad IgnoreOverrides mBuilderVal builderTy - |> List.choose (fun methInfo -> - if not (IsMethInfoAccessible cenv.amap mBuilderVal ad methInfo) then None else - let nameSearch = - TryBindMethInfoAttribute cenv.g mBuilderVal cenv.g.attrib_CustomOperationAttribute methInfo + let customOperationMethods = + AllMethInfosOfTypeInScope + ResultCollectionSettings.AllResults + cenv.infoReader + env.NameEnv + None + ad + IgnoreOverrides + mBuilderVal + builderTy + |> List.choose (fun methInfo -> + if not (IsMethInfoAccessible cenv.amap mBuilderVal ad methInfo) then + None + else + let nameSearch = + TryBindMethInfoAttribute + cenv.g + mBuilderVal + cenv.g.attrib_CustomOperationAttribute + methInfo IgnoreAttribute // We do not respect this attribute for IL methods - (function Attrib(_, _, [ AttribStringArg msg ], _, _, _, _) -> Some msg | _ -> None) + (fun attr -> + // NOTE: right now, we support of custom operations with spaces in them ([]) + // In the parameterless CustomOperationAttribute - we use the method name, and also allow it to be ````-quoted (member _.``foo bar`` _ = ...) + match attr with + // Empty string and parameterless constructor - we use the method name + | Attrib(unnamedArgs = [ AttribStringArg "" ]) // Empty string as parameter + | Attrib(unnamedArgs = []) -> // No parameters, same as empty string for compat reasons. + Some methInfo.LogicalName + // Use the specified name + | Attrib(unnamedArgs = [ AttribStringArg msg ]) -> Some msg + | _ -> None) IgnoreAttribute // We do not respect this attribute for provided methods match nameSearch with | None -> None | Some nm -> let joinConditionWord = - TryBindMethInfoAttribute cenv.g mBuilderVal cenv.g.attrib_CustomOperationAttribute methInfo + TryBindMethInfoAttribute + cenv.g + mBuilderVal + cenv.g.attrib_CustomOperationAttribute + methInfo IgnoreAttribute // We do not respect this attribute for IL methods - (function Attrib(_, _, _, ExtractAttribNamedArg "JoinConditionWord" (AttribStringArg s), _, _, _) -> Some s | _ -> None) + (function + | Attrib(propVal = ExtractAttribNamedArg "JoinConditionWord" (AttribStringArg s)) -> Some s + | _ -> None) IgnoreAttribute // We do not respect this attribute for provided methods - let flagSearch (propName: string) = - TryBindMethInfoAttribute cenv.g mBuilderVal cenv.g.attrib_CustomOperationAttribute methInfo + let flagSearch (propName: string) = + TryBindMethInfoAttribute + cenv.g + mBuilderVal + cenv.g.attrib_CustomOperationAttribute + methInfo IgnoreAttribute // We do not respect this attribute for IL methods - (function Attrib(_, _, _, ExtractAttribNamedArg propName (AttribBoolArg b), _, _, _) -> Some b | _ -> None) + (function + | Attrib(propVal = ExtractAttribNamedArg propName (AttribBoolArg b)) -> Some b + | _ -> None) IgnoreAttribute // We do not respect this attribute for provided methods - let maintainsVarSpaceUsingBind = defaultArg (flagSearch "MaintainsVariableSpaceUsingBind") false + let maintainsVarSpaceUsingBind = + defaultArg (flagSearch "MaintainsVariableSpaceUsingBind") false + let maintainsVarSpace = defaultArg (flagSearch "MaintainsVariableSpace") false let allowInto = defaultArg (flagSearch "AllowIntoPattern") false let isLikeZip = defaultArg (flagSearch "IsLikeZip") false let isLikeJoin = defaultArg (flagSearch "IsLikeJoin") false let isLikeGroupJoin = defaultArg (flagSearch "IsLikeGroupJoin") false - Some (nm, maintainsVarSpaceUsingBind, maintainsVarSpace, allowInto, isLikeZip, isLikeJoin, isLikeGroupJoin, joinConditionWord, methInfo)) - - let customOperationMethodsIndexedByKeyword = + Some( + nm, + maintainsVarSpaceUsingBind, + maintainsVarSpace, + allowInto, + isLikeZip, + isLikeJoin, + isLikeGroupJoin, + joinConditionWord, + methInfo + )) + + let customOperationMethodsIndexedByKeyword = if cenv.g.langVersion.SupportsFeature LanguageFeature.OverloadsForCustomOperations then customOperationMethods |> Seq.groupBy (fun (nm, _, _, _, _, _, _, _, _) -> nm) - |> Seq.map (fun (nm, group) -> - (nm, - group - |> Seq.toList)) + |> Seq.map (fun (nm, group) -> (nm, group |> Seq.toList)) else customOperationMethods |> Seq.groupBy (fun (nm, _, _, _, _, _, _, _, _) -> nm) @@ -315,14 +385,11 @@ let TcComputationExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (mWhol |> dict // Check for duplicates by method name (keywords and method names must be 1:1) - let customOperationMethodsIndexedByMethodName = + let customOperationMethodsIndexedByMethodName = if cenv.g.langVersion.SupportsFeature LanguageFeature.OverloadsForCustomOperations then customOperationMethods |> Seq.groupBy (fun (_, _, _, _, _, _, _, _, methInfo) -> methInfo.LogicalName) - |> Seq.map (fun (nm, group) -> - (nm, - group - |> Seq.toList)) + |> Seq.map (fun (nm, group) -> (nm, group |> Seq.toList)) else customOperationMethods |> Seq.groupBy (fun (_, _, _, _, _, _, _, _, methInfo) -> methInfo.LogicalName) @@ -333,1189 +400,2003 @@ let TcComputationExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (mWhol let tryGetDataForCustomOperation (nm: Ident) = let isOpDataCountAllowed opDatas = match opDatas with - | [_] -> true + | [ _ ] -> true | _ :: _ -> cenv.g.langVersion.SupportsFeature LanguageFeature.OverloadsForCustomOperations | _ -> false - match customOperationMethodsIndexedByKeyword.TryGetValue nm.idText with - | true, opDatas when isOpDataCountAllowed opDatas -> + match customOperationMethodsIndexedByKeyword.TryGetValue nm.idText with + | true, opDatas when isOpDataCountAllowed opDatas -> for opData in opDatas do - let opName, maintainsVarSpaceUsingBind, maintainsVarSpace, _allowInto, isLikeZip, isLikeJoin, isLikeGroupJoin, _joinConditionWord, methInfo = opData - if (maintainsVarSpaceUsingBind && maintainsVarSpace) || (isLikeZip && isLikeJoin) || (isLikeZip && isLikeGroupJoin) || (isLikeJoin && isLikeGroupJoin) then - errorR(Error(FSComp.SR.tcCustomOperationInvalid opName, nm.idRange)) + let (opName, + maintainsVarSpaceUsingBind, + maintainsVarSpace, + _allowInto, + isLikeZip, + isLikeJoin, + isLikeGroupJoin, + _joinConditionWord, + methInfo) = + opData + + if + (maintainsVarSpaceUsingBind && maintainsVarSpace) + || (isLikeZip && isLikeJoin) + || (isLikeZip && isLikeGroupJoin) + || (isLikeJoin && isLikeGroupJoin) + then + errorR (Error(FSComp.SR.tcCustomOperationInvalid opName, nm.idRange)) + if not (cenv.g.langVersion.SupportsFeature LanguageFeature.OverloadsForCustomOperations) then - match customOperationMethodsIndexedByMethodName.TryGetValue methInfo.LogicalName with - | true, [_] -> () - | _ -> errorR(Error(FSComp.SR.tcCustomOperationMayNotBeOverloaded nm.idText, nm.idRange)) + match customOperationMethodsIndexedByMethodName.TryGetValue methInfo.LogicalName with + | true, [ _ ] -> () + | _ -> errorR (Error(FSComp.SR.tcCustomOperationMayNotBeOverloaded nm.idText, nm.idRange)) + Some opDatas - | true, opData :: _ -> errorR(Error(FSComp.SR.tcCustomOperationMayNotBeOverloaded nm.idText, nm.idRange)); Some [opData] + | true, opData :: _ -> + errorR (Error(FSComp.SR.tcCustomOperationMayNotBeOverloaded nm.idText, nm.idRange)) + Some [ opData ] | _ -> None /// Decide if the identifier represents a use of a custom query operator - let hasCustomOperations () = if isNil customOperationMethods then CustomOperationsMode.Denied else CustomOperationsMode.Allowed + let hasCustomOperations () = + if isNil customOperationMethods then + CustomOperationsMode.Denied + else + CustomOperationsMode.Allowed - let isCustomOperation nm = tryGetDataForCustomOperation nm |> Option.isSome + let isCustomOperation nm = + tryGetDataForCustomOperation nm |> Option.isSome - let customOperationCheckValidity m f opDatas = + let customOperationCheckValidity m f opDatas = let vs = opDatas |> List.map f let v0 = vs[0] - let opName, _maintainsVarSpaceUsingBind, _maintainsVarSpace, _allowInto, _isLikeZip, _isLikeJoin, _isLikeGroupJoin, _joinConditionWord, _methInfo = opDatas[0] - if not (List.allEqual vs) then - errorR(Error(FSComp.SR.tcCustomOperationInvalid opName, m)) + + let (opName, + _maintainsVarSpaceUsingBind, + _maintainsVarSpace, + _allowInto, + _isLikeZip, + _isLikeJoin, + _isLikeGroupJoin, + _joinConditionWord, + _methInfo) = + opDatas[0] + + if not (List.allEqual vs) then + errorR (Error(FSComp.SR.tcCustomOperationInvalid opName, m)) + v0 // Check for the MaintainsVariableSpace on custom operation - let customOperationMaintainsVarSpace (nm: Ident) = - match tryGetDataForCustomOperation nm with + let customOperationMaintainsVarSpace (nm: Ident) = + match tryGetDataForCustomOperation nm with | None -> false | Some opDatas -> - opDatas |> customOperationCheckValidity nm.idRange (fun (_nm, _maintainsVarSpaceUsingBind, maintainsVarSpace, _allowInto, _isLikeZip, _isLikeJoin, _isLikeGroupJoin, _joinConditionWord, _methInfo) -> maintainsVarSpace) - - let customOperationMaintainsVarSpaceUsingBind (nm: Ident) = - match tryGetDataForCustomOperation nm with + opDatas + |> customOperationCheckValidity + nm.idRange + (fun + (_nm, + _maintainsVarSpaceUsingBind, + maintainsVarSpace, + _allowInto, + _isLikeZip, + _isLikeJoin, + _isLikeGroupJoin, + _joinConditionWord, + _methInfo) -> maintainsVarSpace) + + let customOperationMaintainsVarSpaceUsingBind (nm: Ident) = + match tryGetDataForCustomOperation nm with | None -> false | Some opDatas -> - opDatas |> customOperationCheckValidity nm.idRange (fun (_nm, maintainsVarSpaceUsingBind, _maintainsVarSpace, _allowInto, _isLikeZip, _isLikeJoin, _isLikeGroupJoin, _joinConditionWord, _methInfo) -> maintainsVarSpaceUsingBind) - - let customOperationIsLikeZip (nm: Ident) = - match tryGetDataForCustomOperation nm with + opDatas + |> customOperationCheckValidity + nm.idRange + (fun + (_nm, + maintainsVarSpaceUsingBind, + _maintainsVarSpace, + _allowInto, + _isLikeZip, + _isLikeJoin, + _isLikeGroupJoin, + _joinConditionWord, + _methInfo) -> maintainsVarSpaceUsingBind) + + let customOperationIsLikeZip (nm: Ident) = + match tryGetDataForCustomOperation nm with | None -> false | Some opDatas -> - opDatas |> customOperationCheckValidity nm.idRange (fun (_nm, _maintainsVarSpaceUsingBind, _maintainsVarSpace, _allowInto, isLikeZip, _isLikeJoin, _isLikeGroupJoin, _joinConditionWord, _methInfo) -> isLikeZip) - - let customOperationIsLikeJoin (nm: Ident) = - match tryGetDataForCustomOperation nm with + opDatas + |> customOperationCheckValidity + nm.idRange + (fun + (_nm, + _maintainsVarSpaceUsingBind, + _maintainsVarSpace, + _allowInto, + isLikeZip, + _isLikeJoin, + _isLikeGroupJoin, + _joinConditionWord, + _methInfo) -> isLikeZip) + + let customOperationIsLikeJoin (nm: Ident) = + match tryGetDataForCustomOperation nm with | None -> false | Some opDatas -> - opDatas |> customOperationCheckValidity nm.idRange (fun (_nm, _maintainsVarSpaceUsingBind, _maintainsVarSpace, _allowInto, _isLikeZip, isLikeJoin, _isLikeGroupJoin, _joinConditionWord, _methInfo) -> isLikeJoin) - - let customOperationIsLikeGroupJoin (nm: Ident) = - match tryGetDataForCustomOperation nm with + opDatas + |> customOperationCheckValidity + nm.idRange + (fun + (_nm, + _maintainsVarSpaceUsingBind, + _maintainsVarSpace, + _allowInto, + _isLikeZip, + isLikeJoin, + _isLikeGroupJoin, + _joinConditionWord, + _methInfo) -> isLikeJoin) + + let customOperationIsLikeGroupJoin (nm: Ident) = + match tryGetDataForCustomOperation nm with | None -> false | Some opDatas -> - opDatas |> customOperationCheckValidity nm.idRange (fun (_nm, _maintainsVarSpaceUsingBind, _maintainsVarSpace, _allowInto, _isLikeZip, _isLikeJoin, isLikeGroupJoin, _joinConditionWord, _methInfo) -> isLikeGroupJoin) - - let customOperationJoinConditionWord (nm: Ident) = - match tryGetDataForCustomOperation nm with + opDatas + |> customOperationCheckValidity + nm.idRange + (fun + (_nm, + _maintainsVarSpaceUsingBind, + _maintainsVarSpace, + _allowInto, + _isLikeZip, + _isLikeJoin, + isLikeGroupJoin, + _joinConditionWord, + _methInfo) -> isLikeGroupJoin) + + let customOperationJoinConditionWord (nm: Ident) = + match tryGetDataForCustomOperation nm with | Some opDatas -> - opDatas |> customOperationCheckValidity nm.idRange (fun (_nm, _maintainsVarSpaceUsingBind, _maintainsVarSpace, _allowInto, _isLikeZip, _isLikeJoin, _isLikeGroupJoin, joinConditionWord, _methInfo) -> joinConditionWord) - |> function None -> "on" | Some v -> v - | _ -> "on" - - let customOperationAllowsInto (nm: Ident) = - match tryGetDataForCustomOperation nm with + opDatas + |> customOperationCheckValidity + nm.idRange + (fun + (_nm, + _maintainsVarSpaceUsingBind, + _maintainsVarSpace, + _allowInto, + _isLikeZip, + _isLikeJoin, + _isLikeGroupJoin, + joinConditionWord, + _methInfo) -> joinConditionWord) + |> function + | None -> "on" + | Some v -> v + | _ -> "on" + + let customOperationAllowsInto (nm: Ident) = + match tryGetDataForCustomOperation nm with | None -> false | Some opDatas -> - opDatas |> customOperationCheckValidity nm.idRange (fun (_nm, _maintainsVarSpaceUsingBind, _maintainsVarSpace, allowInto, _isLikeZip, _isLikeJoin, _isLikeGroupJoin, _joinConditionWord, _methInfo) -> allowInto) - - let customOpUsageText nm = + opDatas + |> customOperationCheckValidity + nm.idRange + (fun + (_nm, + _maintainsVarSpaceUsingBind, + _maintainsVarSpace, + allowInto, + _isLikeZip, + _isLikeJoin, + _isLikeGroupJoin, + _joinConditionWord, + _methInfo) -> allowInto) + + let customOpUsageText nm = match tryGetDataForCustomOperation nm with - | Some ((_nm, _maintainsVarSpaceUsingBind, _maintainsVarSpace, _allowInto, isLikeZip, isLikeJoin, isLikeGroupJoin, _joinConditionWord, _methInfo) :: _) -> + | Some((_nm, + _maintainsVarSpaceUsingBind, + _maintainsVarSpace, + _allowInto, + isLikeZip, + isLikeJoin, + isLikeGroupJoin, + _joinConditionWord, + _methInfo) :: _) -> if isLikeGroupJoin then - Some (FSComp.SR.customOperationTextLikeGroupJoin(nm.idText, customOperationJoinConditionWord nm, customOperationJoinConditionWord nm)) + Some( + FSComp.SR.customOperationTextLikeGroupJoin ( + nm.idText, + customOperationJoinConditionWord nm, + customOperationJoinConditionWord nm + ) + ) elif isLikeJoin then - Some (FSComp.SR.customOperationTextLikeJoin(nm.idText, customOperationJoinConditionWord nm, customOperationJoinConditionWord nm)) + Some( + FSComp.SR.customOperationTextLikeJoin ( + nm.idText, + customOperationJoinConditionWord nm, + customOperationJoinConditionWord nm + ) + ) elif isLikeZip then - Some (FSComp.SR.customOperationTextLikeZip(nm.idText)) + Some(FSComp.SR.customOperationTextLikeZip (nm.idText)) else None - | _ -> None + | _ -> None /// Inside the 'query { ... }' use a modified name environment that contains fake 'CustomOperation' entries /// for all custom operations. This adds them to the completion lists and prevents them being used as values inside /// the query. - let env = - if List.isEmpty customOperationMethods then env else - { env with - eNameResEnv = - (env.eNameResEnv, customOperationMethods) - ||> Seq.fold (fun nenv (nm, _, _, _, _, _, _, _, methInfo) -> - AddFakeNameToNameEnv nm nenv (Item.CustomOperation (nm, (fun () -> customOpUsageText (ident (nm, mBuilderVal))), Some methInfo))) } + let env = + if List.isEmpty customOperationMethods then + env + else + { env with + eNameResEnv = + (env.eNameResEnv, customOperationMethods) + ||> Seq.fold (fun nenv (nm, _, _, _, _, _, _, _, methInfo) -> + AddFakeNameToNameEnv + nm + nenv + (Item.CustomOperation(nm, (fun () -> customOpUsageText (ident (nm, mBuilderVal))), Some methInfo))) + } // Environment is needed for completions CallEnvSink cenv.tcSink (comp.Range, env.NameEnv, ad) - let tryGetArgAttribsForCustomOperator (nm: Ident) = - match tryGetDataForCustomOperation nm with - | Some argInfos -> - argInfos - |> List.map (fun (_nm, __maintainsVarSpaceUsingBind, _maintainsVarSpace, _allowInto, _isLikeZip, _isLikeJoin, _isLikeGroupJoin, _joinConditionWord, methInfo) -> - match methInfo.GetParamAttribs(cenv.amap, mWhole) with - | [curriedArgInfo] -> Some curriedArgInfo // one for the actual argument group - | _ -> None) + let tryGetArgAttribsForCustomOperator (nm: Ident) = + match tryGetDataForCustomOperation nm with + | Some argInfos -> + argInfos + |> List.map + (fun + (_nm, + __maintainsVarSpaceUsingBind, + _maintainsVarSpace, + _allowInto, + _isLikeZip, + _isLikeJoin, + _isLikeGroupJoin, + _joinConditionWord, + methInfo) -> + match methInfo.GetParamAttribs(cenv.amap, mWhole) with + | [ curriedArgInfo ] -> Some curriedArgInfo // one for the actual argument group + | _ -> None) |> Some | _ -> None - let tryGetArgInfosForCustomOperator (nm: Ident) = - match tryGetDataForCustomOperation nm with - | Some argInfos -> - argInfos - |> List.map (fun (_nm, __maintainsVarSpaceUsingBind, _maintainsVarSpace, _allowInto, _isLikeZip, _isLikeJoin, _isLikeGroupJoin, _joinConditionWord, methInfo) -> - match methInfo with - | FSMeth(_, _, vref, _) -> - match ArgInfosOfMember cenv.g vref with - | [curriedArgInfo] -> Some curriedArgInfo - | _ -> None - | _ -> None) + let tryGetArgInfosForCustomOperator (nm: Ident) = + match tryGetDataForCustomOperation nm with + | Some argInfos -> + argInfos + |> List.map + (fun + (_nm, + __maintainsVarSpaceUsingBind, + _maintainsVarSpace, + _allowInto, + _isLikeZip, + _isLikeJoin, + _isLikeGroupJoin, + _joinConditionWord, + methInfo) -> + match methInfo with + | FSMeth(_, _, vref, _) -> + match ArgInfosOfMember cenv.g vref with + | [ curriedArgInfo ] -> Some curriedArgInfo + | _ -> None + | _ -> None) |> Some | _ -> None - let tryExpectedArgCountForCustomOperator (nm: Ident) = - match tryGetArgAttribsForCustomOperator nm with + let tryExpectedArgCountForCustomOperator (nm: Ident) = + match tryGetArgAttribsForCustomOperator nm with | None -> None - | Some argInfosForOverloads -> - let nums = argInfosForOverloads |> List.map (function None -> -1 | Some argInfos -> List.length argInfos) + | Some argInfosForOverloads -> + let nums = + argInfosForOverloads + |> List.map (function + | None -> -1 + | Some argInfos -> List.length argInfos) // Prior to 'OverloadsForCustomOperations' we count exact arguments. // // With 'OverloadsForCustomOperations' we don't compute an exact expected argument count // if any arguments are optional, out or ParamArray. - let isSpecial = + let isSpecial = if cenv.g.langVersion.SupportsFeature LanguageFeature.OverloadsForCustomOperations then - argInfosForOverloads |> List.exists (fun info -> - match info with + argInfosForOverloads + |> List.exists (fun info -> + match info with | None -> false - | Some args -> - args |> List.exists (fun (ParamAttribs(isParamArrayArg, _isInArg, isOutArg, optArgInfo, _callerInfo, _reflArgInfo)) -> isParamArrayArg || isOutArg || optArgInfo.IsOptional)) + | Some args -> + args + |> List.exists + (fun (ParamAttribs(isParamArrayArg, _isInArg, isOutArg, optArgInfo, _callerInfo, _reflArgInfo)) -> + isParamArrayArg || isOutArg || optArgInfo.IsOptional)) else false - if not isSpecial && nums |> List.forall (fun v -> v >= 0 && v = nums[0]) then - Some (max (nums[0] - 1) 0) // drop the computation context argument + if not isSpecial && nums |> List.forall (fun v -> v >= 0 && v = nums[0]) then + Some(max (nums[0] - 1) 0) // drop the computation context argument else None // Check for the [] attribute on an argument position - let isCustomOperationProjectionParameter i (nm: Ident) = + let isCustomOperationProjectionParameter i (nm: Ident) = match tryGetArgInfosForCustomOperator nm with | None -> false | Some argInfosForOverloads -> - let vs = - argInfosForOverloads |> List.map (function + let vs = + argInfosForOverloads + |> List.map (function | None -> false - | Some argInfos -> - i < argInfos.Length && - let _, argInfo = List.item i argInfos - HasFSharpAttribute cenv.g cenv.g.attrib_ProjectionParameterAttribute argInfo.Attribs) - if List.allEqual vs then vs[0] - else + | Some argInfos -> + i < argInfos.Length + && let _, argInfo = List.item i argInfos in + HasFSharpAttribute cenv.g cenv.g.attrib_ProjectionParameterAttribute argInfo.Attribs) + + if List.allEqual vs then + vs[0] + else let opDatas = (tryGetDataForCustomOperation nm).Value let opName, _, _, _, _, _, _, _j, _ = opDatas[0] - errorR(Error(FSComp.SR.tcCustomOperationInvalid opName, nm.idRange)) + errorR (Error(FSComp.SR.tcCustomOperationInvalid opName, nm.idRange)) false - let (|ForEachThen|_|) synExpr = - match synExpr with - | SynExpr.ForEach (_spFor, _spIn, SeqExprOnly false, isFromSource, pat1, expr1, SynExpr.Sequential (_, true, clause, rest, _), _) -> - Some (isFromSource, pat1, expr1, clause, rest) + let (|ForEachThen|_|) synExpr = + match synExpr with + | SynExpr.ForEach(_spFor, _spIn, SeqExprOnly false, isFromSource, pat1, expr1, SynExpr.Sequential(_, true, clause, rest, _), _) -> + Some(isFromSource, pat1, expr1, clause, rest) | _ -> None - let (|CustomOpId|_|) predicate synExpr = - match synExpr with + let (|CustomOpId|_|) predicate synExpr = + match synExpr with | SingleIdent nm when isCustomOperation nm && predicate nm -> Some nm | _ -> None // e1 in e2 ('in' is parsed as 'JOIN_IN') - let (|InExpr|_|) synExpr = - match synExpr with - | SynExpr.JoinIn (e1, _, e2, mApp) -> Some (e1, e2, mApp) + let (|InExpr|_|) synExpr = + match synExpr with + | SynExpr.JoinIn(e1, _, e2, mApp) -> Some(e1, e2, mApp) | _ -> None // e1 on e2 (note: 'on' is the 'JoinConditionWord') - let (|OnExpr|_|) nm synExpr = - match tryGetDataForCustomOperation nm with + let (|OnExpr|_|) nm synExpr = + match tryGetDataForCustomOperation nm with | None -> None - | Some _ -> - match synExpr with - | SynExpr.App (_, _, SynExpr.App (_, _, e1, SingleIdent opName, _), e2, _) when opName.idText = customOperationJoinConditionWord nm -> - let item = Item.CustomOperation (opName.idText, (fun () -> None), None) + | Some _ -> + match synExpr with + | SynExpr.App(funcExpr = SynExpr.App(funcExpr = e1; argExpr = SingleIdent opName); argExpr = e2) when + opName.idText = customOperationJoinConditionWord nm + -> + let item = Item.CustomOperation(opName.idText, (fun () -> None), None) CallNameResolutionSink cenv.tcSink (opName.idRange, env.NameEnv, item, emptyTyparInst, ItemOccurence.Use, env.AccessRights) - Some (e1, e2) + Some(e1, e2) | _ -> None // e1 into e2 - let (|IntoSuffix|_|) (e: SynExpr) = - match e with - | SynExpr.App (_, _, SynExpr.App (_, _, x, SingleIdent nm2, _), ExprAsPat intoPat, _) when nm2.idText = CustomOperations.Into -> - Some (x, nm2.idRange, intoPat) - | _ -> - None + let (|IntoSuffix|_|) (e: SynExpr) = + match e with + | SynExpr.App(funcExpr = SynExpr.App(funcExpr = x; argExpr = SingleIdent nm2); argExpr = ExprAsPat intoPat) when + nm2.idText = CustomOperations.Into + -> + Some(x, nm2.idRange, intoPat) + | _ -> None - let arbPat (m: range) = mkSynPatVar None (mkSynId (m.MakeSynthetic()) "_missingVar") + let arbPat (m: range) = + mkSynPatVar None (mkSynId (m.MakeSynthetic()) "_missingVar") - let MatchIntoSuffixOrRecover alreadyGivenError (nm: Ident) synExpr = - match synExpr with - | IntoSuffix (x, intoWordRange, intoPat) -> + let MatchIntoSuffixOrRecover alreadyGivenError (nm: Ident) synExpr = + match synExpr with + | IntoSuffix(x, intoWordRange, intoPat) -> // record the "into" as a custom operation for colorization - let item = Item.CustomOperation ("into", (fun () -> None), None) + let item = Item.CustomOperation("into", (fun () -> None), None) CallNameResolutionSink cenv.tcSink (intoWordRange, env.NameEnv, item, emptyTyparInst, ItemOccurence.Use, env.eAccessRights) (x, intoPat, alreadyGivenError) - | _ -> - if not alreadyGivenError then - errorR(Error(FSComp.SR.tcOperatorIncorrectSyntax(nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) + | _ -> + if not alreadyGivenError then + errorR (Error(FSComp.SR.tcOperatorIncorrectSyntax (nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) + (synExpr, arbPat synExpr.Range, true) - let MatchOnExprOrRecover alreadyGivenError nm (onExpr: SynExpr) = - match onExpr with - | OnExpr nm (innerSource, SynExprParen(keySelectors, _, _, _)) -> - (innerSource, keySelectors) - | _ -> - if not alreadyGivenError then - suppressErrorReporting (fun () -> TcExprOfUnknownType cenv env tpenv onExpr) |> ignore - errorR(Error(FSComp.SR.tcOperatorIncorrectSyntax(nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) - (arbExpr("_innerSource", onExpr.Range), mkSynBifix onExpr.Range "=" (arbExpr("_keySelectors", onExpr.Range)) (arbExpr("_keySelector2", onExpr.Range))) - - let JoinOrGroupJoinOp detector synExpr = - match synExpr with - | SynExpr.App (_, _, CustomOpId detector nm, ExprAsPat innerSourcePat, mJoinCore) -> - Some(nm, innerSourcePat, mJoinCore, false) + let MatchOnExprOrRecover alreadyGivenError nm (onExpr: SynExpr) = + match onExpr with + | OnExpr nm (innerSource, SynExprParen(keySelectors, _, _, _)) -> (innerSource, keySelectors) + | _ -> + if not alreadyGivenError then + suppressErrorReporting (fun () -> TcExprOfUnknownType cenv env tpenv onExpr) + |> ignore + + errorR (Error(FSComp.SR.tcOperatorIncorrectSyntax (nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) + + (arbExpr ("_innerSource", onExpr.Range), + mkSynBifix onExpr.Range "=" (arbExpr ("_keySelectors", onExpr.Range)) (arbExpr ("_keySelector2", onExpr.Range))) + + let JoinOrGroupJoinOp detector synExpr = + match synExpr with + | SynExpr.App(_, _, CustomOpId detector nm, ExprAsPat innerSourcePat, mJoinCore) -> Some(nm, innerSourcePat, mJoinCore, false) // join with bad pattern (gives error on "join" and continues) - | SynExpr.App (_, _, CustomOpId detector nm, _innerSourcePatExpr, mJoinCore) -> - errorR(Error(FSComp.SR.tcBinaryOperatorRequiresVariable(nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) + | SynExpr.App(_, _, CustomOpId detector nm, _innerSourcePatExpr, mJoinCore) -> + errorR (Error(FSComp.SR.tcBinaryOperatorRequiresVariable (nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) Some(nm, arbPat mJoinCore, mJoinCore, true) // join (without anything after - gives error on "join" and continues) - | CustomOpId detector nm -> - errorR(Error(FSComp.SR.tcBinaryOperatorRequiresVariable(nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) + | CustomOpId detector nm -> + errorR (Error(FSComp.SR.tcBinaryOperatorRequiresVariable (nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) Some(nm, arbPat synExpr.Range, synExpr.Range, true) - | _ -> - None - // JoinOrGroupJoinOp customOperationIsLikeJoin + | _ -> None + // JoinOrGroupJoinOp customOperationIsLikeJoin - let (|JoinOp|_|) synExpr = JoinOrGroupJoinOp customOperationIsLikeJoin synExpr + let (|JoinOp|_|) synExpr = + JoinOrGroupJoinOp customOperationIsLikeJoin synExpr - let (|GroupJoinOp|_|) synExpr = JoinOrGroupJoinOp customOperationIsLikeGroupJoin synExpr + let (|GroupJoinOp|_|) synExpr = + JoinOrGroupJoinOp customOperationIsLikeGroupJoin synExpr - let arbKeySelectors m = mkSynBifix m "=" (arbExpr("_keySelectors", m)) (arbExpr("_keySelector2", m)) + let arbKeySelectors m = + mkSynBifix m "=" (arbExpr ("_keySelectors", m)) (arbExpr ("_keySelector2", m)) - let (|JoinExpr|_|) synExpr = - match synExpr with - | InExpr (JoinOp(nm, innerSourcePat, _, alreadyGivenError), onExpr, mJoinCore) -> + let (|JoinExpr|_|) synExpr = + match synExpr with + | InExpr(JoinOp(nm, innerSourcePat, _, alreadyGivenError), onExpr, mJoinCore) -> let innerSource, keySelectors = MatchOnExprOrRecover alreadyGivenError nm onExpr Some(nm, innerSourcePat, innerSource, keySelectors, mJoinCore) - | JoinOp (nm, innerSourcePat, mJoinCore, alreadyGivenError) -> - if alreadyGivenError then - errorR(Error(FSComp.SR.tcOperatorRequiresIn(nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) - Some (nm, innerSourcePat, arbExpr("_innerSource", synExpr.Range), arbKeySelectors synExpr.Range, mJoinCore) + | JoinOp(nm, innerSourcePat, mJoinCore, alreadyGivenError) -> + if alreadyGivenError then + errorR (Error(FSComp.SR.tcOperatorRequiresIn (nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) + + Some(nm, innerSourcePat, arbExpr ("_innerSource", synExpr.Range), arbKeySelectors synExpr.Range, mJoinCore) | _ -> None - let (|GroupJoinExpr|_|) synExpr = - match synExpr with - | InExpr (GroupJoinOp (nm, innerSourcePat, _, alreadyGivenError), intoExpr, mGroupJoinCore) -> - let onExpr, intoPat, alreadyGivenError = MatchIntoSuffixOrRecover alreadyGivenError nm intoExpr - let innerSource, keySelectors = MatchOnExprOrRecover alreadyGivenError nm onExpr - Some (nm, innerSourcePat, innerSource, keySelectors, intoPat, mGroupJoinCore) - | GroupJoinOp (nm, innerSourcePat, mGroupJoinCore, alreadyGivenError) -> - if alreadyGivenError then - errorR(Error(FSComp.SR.tcOperatorRequiresIn(nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) - Some (nm, innerSourcePat, arbExpr("_innerSource", synExpr.Range), arbKeySelectors synExpr.Range, arbPat synExpr.Range, mGroupJoinCore) - | _ -> - None + let (|GroupJoinExpr|_|) synExpr = + match synExpr with + | InExpr(GroupJoinOp(nm, innerSourcePat, _, alreadyGivenError), intoExpr, mGroupJoinCore) -> + let onExpr, intoPat, alreadyGivenError = + MatchIntoSuffixOrRecover alreadyGivenError nm intoExpr + let innerSource, keySelectors = MatchOnExprOrRecover alreadyGivenError nm onExpr + Some(nm, innerSourcePat, innerSource, keySelectors, intoPat, mGroupJoinCore) + | GroupJoinOp(nm, innerSourcePat, mGroupJoinCore, alreadyGivenError) -> + if alreadyGivenError then + errorR (Error(FSComp.SR.tcOperatorRequiresIn (nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) + + Some( + nm, + innerSourcePat, + arbExpr ("_innerSource", synExpr.Range), + arbKeySelectors synExpr.Range, + arbPat synExpr.Range, + mGroupJoinCore + ) + | _ -> None - let (|JoinOrGroupJoinOrZipClause|_|) synExpr = + let (|JoinOrGroupJoinOrZipClause|_|) synExpr = - match synExpr with + match synExpr with // join innerSourcePat in innerSource on (keySelector1 = keySelector2) - | JoinExpr (nm, innerSourcePat, innerSource, keySelectors, mJoinCore) -> + | JoinExpr(nm, innerSourcePat, innerSource, keySelectors, mJoinCore) -> Some(nm, innerSourcePat, innerSource, Some keySelectors, None, mJoinCore) // groupJoin innerSourcePat in innerSource on (keySelector1 = keySelector2) into intoPat - | GroupJoinExpr (nm, innerSourcePat, innerSource, keySelectors, intoPat, mGroupJoinCore) -> + | GroupJoinExpr(nm, innerSourcePat, innerSource, keySelectors, intoPat, mGroupJoinCore) -> Some(nm, innerSourcePat, innerSource, Some keySelectors, Some intoPat, mGroupJoinCore) - // zip intoPat in secondSource - | InExpr (SynExpr.App (_, _, CustomOpId customOperationIsLikeZip nm, ExprAsPat secondSourcePat, _), secondSource, mZipCore) -> + // zip intoPat in secondSource + | InExpr(SynExpr.App(_, _, CustomOpId customOperationIsLikeZip nm, ExprAsPat secondSourcePat, _), secondSource, mZipCore) -> Some(nm, secondSourcePat, secondSource, None, None, mZipCore) // zip (without secondSource or in - gives error) - | CustomOpId customOperationIsLikeZip nm -> - errorR(Error(FSComp.SR.tcOperatorIncorrectSyntax(nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) - Some(nm, arbPat synExpr.Range, arbExpr("_secondSource", synExpr.Range), None, None, synExpr.Range) + | CustomOpId customOperationIsLikeZip nm -> + errorR (Error(FSComp.SR.tcOperatorIncorrectSyntax (nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) + Some(nm, arbPat synExpr.Range, arbExpr ("_secondSource", synExpr.Range), None, None, synExpr.Range) // zip secondSource (without in - gives error) - | SynExpr.App (_, _, CustomOpId customOperationIsLikeZip nm, ExprAsPat secondSourcePat, mZipCore) -> - errorR(Error(FSComp.SR.tcOperatorIncorrectSyntax(nm.idText, Option.get (customOpUsageText nm)), mZipCore)) - Some(nm, secondSourcePat, arbExpr("_innerSource", synExpr.Range), None, None, mZipCore) + | SynExpr.App(_, _, CustomOpId customOperationIsLikeZip nm, ExprAsPat secondSourcePat, mZipCore) -> + errorR (Error(FSComp.SR.tcOperatorIncorrectSyntax (nm.idText, Option.get (customOpUsageText nm)), mZipCore)) + Some(nm, secondSourcePat, arbExpr ("_innerSource", synExpr.Range), None, None, mZipCore) - | _ -> - None + | _ -> None - let (|ForEachThenJoinOrGroupJoinOrZipClause|_|) strict synExpr = - match synExpr with - | ForEachThen (isFromSource, firstSourcePat, firstSource, JoinOrGroupJoinOrZipClause(nm, secondSourcePat, secondSource, keySelectorsOpt, pat3opt, mOpCore), innerComp) - when - (let _firstSourceSimplePats, later1 = - use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - SimplePatsOfPat cenv.synArgNameGenerator firstSourcePat - Option.isNone later1) -> - Some (isFromSource, firstSourcePat, firstSource, nm, secondSourcePat, secondSource, keySelectorsOpt, pat3opt, mOpCore, innerComp) - - | JoinOrGroupJoinOrZipClause(nm, pat2, expr2, expr3, pat3opt, mOpCore) when strict -> - errorR(Error(FSComp.SR.tcBinaryOperatorRequiresBody(nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) - Some (true, arbPat synExpr.Range, arbExpr("_outerSource", synExpr.Range), nm, pat2, expr2, expr3, pat3opt, mOpCore, arbExpr("_innerComp", synExpr.Range)) - - | _ -> - None + let (|ForEachThenJoinOrGroupJoinOrZipClause|_|) strict synExpr = + match synExpr with + | ForEachThen(isFromSource, + firstSourcePat, + firstSource, + JoinOrGroupJoinOrZipClause(nm, secondSourcePat, secondSource, keySelectorsOpt, pat3opt, mOpCore), + innerComp) when + (let _firstSourceSimplePats, later1 = + use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink + SimplePatsOfPat cenv.synArgNameGenerator firstSourcePat + + Option.isNone later1) + -> + Some(isFromSource, firstSourcePat, firstSource, nm, secondSourcePat, secondSource, keySelectorsOpt, pat3opt, mOpCore, innerComp) + + | JoinOrGroupJoinOrZipClause(nm, pat2, expr2, expr3, pat3opt, mOpCore) when strict -> + errorR (Error(FSComp.SR.tcBinaryOperatorRequiresBody (nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) + + Some( + true, + arbPat synExpr.Range, + arbExpr ("_outerSource", synExpr.Range), + nm, + pat2, + expr2, + expr3, + pat3opt, + mOpCore, + arbExpr ("_innerComp", synExpr.Range) + ) - let (|StripApps|) e = - let rec strip e = - match e with - | SynExpr.FromParseError (SynExpr.App (_, _, f, arg, _), _) - | SynExpr.App (_, _, f, arg, _) -> - let g, acc = strip f - g, (arg :: acc) + | _ -> None + + let (|StripApps|) e = + let rec strip e = + match e with + | SynExpr.FromParseError(SynExpr.App(funcExpr = f; argExpr = arg), _) + | SynExpr.App(funcExpr = f; argExpr = arg) -> + let g, acc = strip f + g, (arg :: acc) | _ -> e, [] + let g, acc = strip e g, List.rev acc - let (|OptionalIntoSuffix|) e = - match e with - | IntoSuffix (body, intoWordRange, intoInfo) -> (body, Some (intoWordRange, intoInfo)) + let (|OptionalIntoSuffix|) e = + match e with + | IntoSuffix(body, intoWordRange, intoInfo) -> (body, Some(intoWordRange, intoInfo)) | body -> (body, None) - let (|CustomOperationClause|_|) e = - match e with - | OptionalIntoSuffix(StripApps(SingleIdent nm, _) as core, intoOpt) when isCustomOperation nm -> + let (|CustomOperationClause|_|) e = + match e with + | OptionalIntoSuffix(StripApps(SingleIdent nm, _) as core, intoOpt) when isCustomOperation nm -> // Now we know we have a custom operation, commit the name resolution - let intoInfoOpt = - match intoOpt with - | Some (intoWordRange, intoInfo) -> - let item = Item.CustomOperation ("into", (fun () -> None), None) - CallNameResolutionSink cenv.tcSink (intoWordRange, env.NameEnv, item, emptyTyparInst, ItemOccurence.Use, env.eAccessRights) + let intoInfoOpt = + match intoOpt with + | Some(intoWordRange, intoInfo) -> + let item = Item.CustomOperation("into", (fun () -> None), None) + + CallNameResolutionSink + cenv.tcSink + (intoWordRange, env.NameEnv, item, emptyTyparInst, ItemOccurence.Use, env.eAccessRights) + Some intoInfo | None -> None - Some (nm, Option.get (tryGetDataForCustomOperation nm), core, core.Range, intoInfoOpt) + Some(nm, Option.get (tryGetDataForCustomOperation nm), core, core.Range, intoInfoOpt) | _ -> None - let mkSynLambda p e m = SynExpr.Lambda (false, false, p, e, None, m, SynExprLambdaTrivia.Zero) + let mkSynLambda p e m = + SynExpr.Lambda(false, false, p, e, None, m, SynExprLambdaTrivia.Zero) - let mkExprForVarSpace m (patvs: Val list) = - match patvs with - | [] -> SynExpr.Const (SynConst.Unit, m) - | [v] -> SynExpr.Ident v.Id - | vs -> SynExpr.Tuple (false, (vs |> List.map (fun v -> SynExpr.Ident(v.Id))), [], m) + let mkExprForVarSpace m (patvs: Val list) = + match patvs with + | [] -> SynExpr.Const(SynConst.Unit, m) + | [ v ] -> SynExpr.Ident v.Id + | vs -> SynExpr.Tuple(false, (vs |> List.map (fun v -> SynExpr.Ident(v.Id))), [], m) - let mkSimplePatForVarSpace m (patvs: Val list) = - let spats = - match patvs with + let mkSimplePatForVarSpace m (patvs: Val list) = + let spats = + match patvs with | [] -> [] - | [v] -> [mkSynSimplePatVar false v.Id] + | [ v ] -> [ mkSynSimplePatVar false v.Id ] | vs -> vs |> List.map (fun v -> mkSynSimplePatVar false v.Id) - SynSimplePats.SimplePats (spats, [], m) - let mkPatForVarSpace m (patvs: Val list) = - match patvs with - | [] -> SynPat.Const (SynConst.Unit, m) - | [v] -> mkSynPatVar None v.Id + SynSimplePats.SimplePats(spats, [], m) + + let mkPatForVarSpace m (patvs: Val list) = + match patvs with + | [] -> SynPat.Const(SynConst.Unit, m) + | [ v ] -> mkSynPatVar None v.Id | vs -> SynPat.Tuple(false, (vs |> List.map (fun x -> mkSynPatVar None x.Id)), [], m) - let (|OptionalSequential|) e = - match e with - | SynExpr.Sequential (_sp, true, dataComp1, dataComp2, _) -> (dataComp1, Some dataComp2) + let (|OptionalSequential|) e = + match e with + | SynExpr.Sequential(_sp, true, dataComp1, dataComp2, _) -> (dataComp1, Some dataComp2) | _ -> (e, None) // "cexpr; cexpr" is treated as builder.Combine(cexpr1, cexpr1) // This is not pretty - we have to decide which range markers we use for the calls to Combine and Delay // NOTE: we should probably suppress these sequence points altogether - let rangeForCombine innerComp1 = + let rangeForCombine innerComp1 = let m = - match innerComp1 with - | SynExpr.IfThenElse (trivia={ IfToThenRange = mIfToThen }) -> mIfToThen - | SynExpr.Match (matchDebugPoint=DebugPointAtBinding.Yes mMatch) -> mMatch - | SynExpr.TryWith (trivia={ TryKeyword = mTry }) -> mTry - | SynExpr.TryFinally (trivia={ TryKeyword = mTry }) -> mTry - | SynExpr.For (forDebugPoint=DebugPointAtFor.Yes mBind) -> mBind - | SynExpr.ForEach (forDebugPoint=DebugPointAtFor.Yes mBind) -> mBind - | SynExpr.While (whileDebugPoint=DebugPointAtWhile.Yes mWhile) -> mWhile + match innerComp1 with + | SynExpr.IfThenElse(trivia = { IfToThenRange = mIfToThen }) -> mIfToThen + | SynExpr.Match(matchDebugPoint = DebugPointAtBinding.Yes mMatch) -> mMatch + | SynExpr.TryWith(trivia = { TryKeyword = mTry }) -> mTry + | SynExpr.TryFinally(trivia = { TryKeyword = mTry }) -> mTry + | SynExpr.For(forDebugPoint = DebugPointAtFor.Yes mBind) -> mBind + | SynExpr.ForEach(forDebugPoint = DebugPointAtFor.Yes mBind) -> mBind + | SynExpr.While(whileDebugPoint = DebugPointAtWhile.Yes mWhile) -> mWhile | _ -> innerComp1.Range m.NoteSourceConstruct(NotedSourceConstruct.Combine) // Check for 'where x > y', 'select x, y' and other mis-applications of infix operators, give a good error message, and return a flag - let checkForBinaryApp comp = - match comp with - | StripApps(SingleIdent nm, [StripApps(SingleIdent nm2, args); arg2]) when - IsLogicalInfixOpName nm.idText && - (match tryExpectedArgCountForCustomOperator nm2 with Some n -> n > 0 | _ -> false) && - not (List.isEmpty args) -> - let estimatedRangeOfIntendedLeftAndRightArguments = unionRanges (List.last args).Range arg2.Range - errorR(Error(FSComp.SR.tcUnrecognizedQueryBinaryOperator(), estimatedRangeOfIntendedLeftAndRightArguments)) + let checkForBinaryApp comp = + match comp with + | StripApps(SingleIdent nm, [ StripApps(SingleIdent nm2, args); arg2 ]) when + IsLogicalInfixOpName nm.idText + && (match tryExpectedArgCountForCustomOperator nm2 with + | Some n -> n > 0 + | _ -> false) + && not (List.isEmpty args) + -> + let estimatedRangeOfIntendedLeftAndRightArguments = + unionRanges (List.last args).Range arg2.Range + + errorR (Error(FSComp.SR.tcUnrecognizedQueryBinaryOperator (), estimatedRangeOfIntendedLeftAndRightArguments)) true - | SynExpr.Tuple (false, StripApps(SingleIdent nm2, args) :: _, _, m) when - (match tryExpectedArgCountForCustomOperator nm2 with Some n -> n > 0 | _ -> false) && - not (List.isEmpty args) -> - let estimatedRangeOfIntendedLeftAndRightArguments = unionRanges (List.last args).Range m.EndRange - errorR(Error(FSComp.SR.tcUnrecognizedQueryBinaryOperator(), estimatedRangeOfIntendedLeftAndRightArguments)) + | SynExpr.Tuple(false, StripApps(SingleIdent nm2, args) :: _, _, m) when + (match tryExpectedArgCountForCustomOperator nm2 with + | Some n -> n > 0 + | _ -> false) + && not (List.isEmpty args) + -> + let estimatedRangeOfIntendedLeftAndRightArguments = + unionRanges (List.last args).Range m.EndRange + + errorR (Error(FSComp.SR.tcUnrecognizedQueryBinaryOperator (), estimatedRangeOfIntendedLeftAndRightArguments)) true - | _ -> - false - - let addVarsToVarSpace (varSpace: LazyWithContext) f = - LazyWithContext.Create - ((fun m -> - let (patvs: Val list, env) = varSpace.Force m - let vs, envinner = f m env - let patvs = List.append patvs (vs |> List.filter (fun v -> not (patvs |> List.exists (fun v2 -> v.LogicalName = v2.LogicalName)))) - patvs, envinner), - id) + | _ -> false + + let addVarsToVarSpace (varSpace: LazyWithContext) f = + LazyWithContext.Create( + (fun m -> + let (patvs: Val list, env) = varSpace.Force m + let vs, envinner = f m env + + let patvs = + List.append + patvs + (vs + |> List.filter (fun v -> not (patvs |> List.exists (fun v2 -> v.LogicalName = v2.LogicalName)))) + + patvs, envinner), + id + ) // Flag that a debug point should get emitted prior to both the evaluation of 'rhsExpr' and the call to Using let addBindDebugPoint spBind e = match spBind with - | DebugPointAtBinding.Yes m -> - SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes m, false, e) + | DebugPointAtBinding.Yes m -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes m, false, e) | _ -> e - let emptyVarSpace = LazyWithContext.NotLazy ([], env) + let emptyVarSpace = LazyWithContext.NotLazy([], env) // If there are no 'yield' in the computation expression, and the builder supports 'Yield', // then allow the type-directed rule interpreting non-unit-typed expressions in statement // positions as 'yield'. 'yield!' may be present in the computation expression. let enableImplicitYield = cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield - && (hasMethInfo "Yield" && hasMethInfo "Combine" && hasMethInfo "Delay" && YieldFree cenv comp) - - // q - a flag indicating if custom operators are allowed. They are not allowed inside try/with, try/finally, if/then/else etc. - // varSpace - a lazy data structure indicating the variables bound so far in the overall computation - // comp - the computation expression being analyzed - // translatedCtxt - represents the translation of the context in which the computation expression 'comp' occurs, up to a - // hole to be filled by (part of) the results of translating 'comp'. - let rec tryTrans firstTry q varSpace comp translatedCtxt = + && (hasMethInfo "Yield" + && hasMethInfo "Combine" + && hasMethInfo "Delay" + && YieldFree cenv comp) + + /// + /// Try translate the syntax sugar + /// + /// + /// a flag indicating if custom operators are allowed. They are not allowed inside try/with, try/finally, if/then/else etc. + /// a lazy data structure indicating the variables bound so far in the overall computation + /// the computation expression being analyzed + /// represents the translation of the context in which the computation expression 'comp' occurs, + /// up to a hole to be filled by (part of) the results of translating 'comp'. + let rec tryTrans + (firstTry: CompExprTranslationPass) + (q: CustomOperationsMode) + (varSpace: LazyWithContext<(Val list * TcEnv), range>) + (comp: SynExpr) + (translatedCtxt: SynExpr -> SynExpr) + : SynExpr option = // Guard the stack for deeply nested computation expressions - cenv.stackGuard.Guard <| fun () -> - - match comp with - - // for firstSourcePat in firstSource do - // join secondSourcePat in expr2 on (expr3 = expr4) - // ... - // --> - // join expr1 expr2 (fun firstSourcePat -> expr3) (fun secondSourcePat -> expr4) (fun firstSourcePat secondSourcePat -> ...) - - // for firstSourcePat in firstSource do - // groupJoin secondSourcePat in expr2 on (expr3 = expr4) into groupPat - // ... - // --> - // groupJoin expr1 expr2 (fun firstSourcePat -> expr3) (fun secondSourcePat -> expr4) (fun firstSourcePat groupPat -> ...) - - // for firstSourcePat in firstSource do - // zip secondSource into secondSourcePat - // ... - // --> - // zip expr1 expr2 (fun pat1 pat3 -> ...) - | ForEachThenJoinOrGroupJoinOrZipClause true (isFromSource, firstSourcePat, firstSource, nm, secondSourcePat, secondSource, keySelectorsOpt, secondResultPatOpt, mOpCore, innerComp) -> - - if q = CustomOperationsMode.Denied then error(Error(FSComp.SR.tcCustomOperationMayNotBeUsedHere(), nm.idRange)) - let firstSource = mkSourceExprConditional isFromSource firstSource - let secondSource = mkSourceExpr secondSource - - // Add the variables to the variable space, on demand - let varSpaceWithFirstVars = - addVarsToVarSpace varSpace (fun _mCustomOp env -> - use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType g) env tpenv firstSourcePat None - vspecs, envinner) - - let varSpaceWithSecondVars = - addVarsToVarSpace varSpaceWithFirstVars (fun _mCustomOp env -> - use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType g) env tpenv secondSourcePat None - vspecs, envinner) - - let varSpaceWithGroupJoinVars = - match secondResultPatOpt with - | Some pat3 -> - addVarsToVarSpace varSpaceWithFirstVars (fun _mCustomOp env -> + cenv.stackGuard.Guard + <| fun () -> + + match comp with + + // for firstSourcePat in firstSource do + // join secondSourcePat in expr2 on (expr3 = expr4) + // ... + // --> + // join expr1 expr2 (fun firstSourcePat -> expr3) (fun secondSourcePat -> expr4) (fun firstSourcePat secondSourcePat -> ...) + + // for firstSourcePat in firstSource do + // groupJoin secondSourcePat in expr2 on (expr3 = expr4) into groupPat + // ... + // --> + // groupJoin expr1 expr2 (fun firstSourcePat -> expr3) (fun secondSourcePat -> expr4) (fun firstSourcePat groupPat -> ...) + + // for firstSourcePat in firstSource do + // zip secondSource into secondSourcePat + // ... + // --> + // zip expr1 expr2 (fun pat1 pat3 -> ...) + | ForEachThenJoinOrGroupJoinOrZipClause true (isFromSource, + firstSourcePat, + firstSource, + nm, + secondSourcePat, + secondSource, + keySelectorsOpt, + secondResultPatOpt, + mOpCore, + innerComp) -> + + if q = CustomOperationsMode.Denied then + error (Error(FSComp.SR.tcCustomOperationMayNotBeUsedHere (), nm.idRange)) + + let firstSource = mkSourceExprConditional isFromSource firstSource + let secondSource = mkSourceExpr secondSource + + // Add the variables to the variable space, on demand + let varSpaceWithFirstVars = + addVarsToVarSpace varSpace (fun _mCustomOp env -> use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType g) env tpenv pat3 None - vspecs, envinner) - | None -> varSpace - let firstSourceSimplePats, later1 = SimplePatsOfPat cenv.synArgNameGenerator firstSourcePat - let secondSourceSimplePats, later2 = SimplePatsOfPat cenv.synArgNameGenerator secondSourcePat + let _, _, vspecs, envinner, _ = + TcMatchPattern cenv (NewInferenceType g) env tpenv firstSourcePat None - if Option.isSome later1 then errorR (Error (FSComp.SR.tcJoinMustUseSimplePattern(nm.idText), firstSourcePat.Range)) - if Option.isSome later2 then errorR (Error (FSComp.SR.tcJoinMustUseSimplePattern(nm.idText), secondSourcePat.Range)) + vspecs, envinner) - // check 'join' or 'groupJoin' or 'zip' is permitted for this builder - match tryGetDataForCustomOperation nm with - | None -> error(Error(FSComp.SR.tcMissingCustomOperation(nm.idText), nm.idRange)) - | Some opDatas -> - let opName, _, _, _, _, _, _, _, methInfo = opDatas[0] + let varSpaceWithSecondVars = + addVarsToVarSpace varSpaceWithFirstVars (fun _mCustomOp env -> + use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - // Record the resolution of the custom operation for posterity - let item = Item.CustomOperation (opName, (fun () -> customOpUsageText nm), Some methInfo) + let _, _, vspecs, envinner, _ = + TcMatchPattern cenv (NewInferenceType g) env tpenv secondSourcePat None - // FUTURE: consider whether we can do better than emptyTyparInst here, in order to display instantiations - // of type variables in the quick info provided in the IDE. - CallNameResolutionSink cenv.tcSink (nm.idRange, env.NameEnv, item, emptyTyparInst, ItemOccurence.Use, env.eAccessRights) + vspecs, envinner) - let mkJoinExpr keySelector1 keySelector2 innerPat e = - let mSynthetic = mOpCore.MakeSynthetic() - mkSynCall methInfo.DisplayName mOpCore - [ firstSource - secondSource - mkSynLambda firstSourceSimplePats keySelector1 mSynthetic - mkSynLambda secondSourceSimplePats keySelector2 mSynthetic - mkSynLambda firstSourceSimplePats (mkSynLambda innerPat e mSynthetic) mSynthetic ] - - let mkZipExpr e = - let mSynthetic = mOpCore.MakeSynthetic() - mkSynCall methInfo.DisplayName mOpCore - [ firstSource - secondSource - mkSynLambda firstSourceSimplePats (mkSynLambda secondSourceSimplePats e mSynthetic) mSynthetic ] - - // wraps given expression into sequence with result produced by arbExpr so result will look like: - // l; SynExpr.ArbitraryAfterError (...) - // this allows to handle cases like 'on (a > b)' // '>' is not permitted as correct join relation - // after wrapping a and b can still be typechecked (so we'll have correct completion inside 'on' part) - // but presence of SynExpr.ArbitraryAfterError allows to avoid errors about incompatible types in cases like - // query { - // for a in [1] do - // join b in [""] on (a > b) - // } - // if we typecheck raw 'a' and 'b' then we'll end up with 2 errors: - // 1. incorrect join relation - // 2. incompatible types: int and string - // with SynExpr.ArbitraryAfterError we have only first one - let wrapInArbErrSequence l caption = - SynExpr.Sequential (DebugPointAtSequential.SuppressNeither, true, l, (arbExpr(caption, l.Range.EndRange)), l.Range) - - let mkOverallExprGivenVarSpaceExpr, varSpaceInner = - - let isNullableOp opId = - match ConvertValLogicalNameToDisplayNameCore opId with - | "?=" | "=?" | "?=?" -> true - | _ -> false - - match secondResultPatOpt, keySelectorsOpt with - // groupJoin - | Some secondResultPat, Some relExpr when customOperationIsLikeGroupJoin nm -> - let secondResultSimplePats, later3 = SimplePatsOfPat cenv.synArgNameGenerator secondResultPat - if Option.isSome later3 then errorR (Error (FSComp.SR.tcJoinMustUseSimplePattern(nm.idText), secondResultPat.Range)) - match relExpr with - | JoinRelation cenv env (keySelector1, keySelector2) -> - mkJoinExpr keySelector1 keySelector2 secondResultSimplePats, varSpaceWithGroupJoinVars - | BinOpExpr (opId, l, r) -> - if isNullableOp opId.idText then - // When we cannot resolve NullableOps, recommend the relevant namespace to be added - errorR(Error(FSComp.SR.cannotResolveNullableOperators(ConvertValLogicalNameToDisplayNameCore opId.idText), relExpr.Range)) - else - errorR(Error(FSComp.SR.tcInvalidRelationInJoin(nm.idText), relExpr.Range)) - let l = wrapInArbErrSequence l "_keySelector1" - let r = wrapInArbErrSequence r "_keySelector2" - // this is not correct JoinRelation but it is still binary operation - // we've already reported error now we can use operands of binary operation as join components - mkJoinExpr l r secondResultSimplePats, varSpaceWithGroupJoinVars - | _ -> - errorR(Error(FSComp.SR.tcInvalidRelationInJoin(nm.idText), relExpr.Range)) - // since the shape of relExpr doesn't match our expectations (JoinRelation) - // then we assume that this is l.h.s. of the join relation - // so typechecker will treat relExpr as body of outerKeySelector lambda parameter in GroupJoin method - mkJoinExpr relExpr (arbExpr("_keySelector2", relExpr.Range)) secondResultSimplePats, varSpaceWithGroupJoinVars - - | None, Some relExpr when customOperationIsLikeJoin nm -> - match relExpr with - | JoinRelation cenv env (keySelector1, keySelector2) -> - mkJoinExpr keySelector1 keySelector2 secondSourceSimplePats, varSpaceWithSecondVars - | BinOpExpr (opId, l, r) -> - if isNullableOp opId.idText then - // When we cannot resolve NullableOps, recommend the relevant namespace to be added - errorR(Error(FSComp.SR.cannotResolveNullableOperators(ConvertValLogicalNameToDisplayNameCore opId.idText), relExpr.Range)) - else - errorR(Error(FSComp.SR.tcInvalidRelationInJoin(nm.idText), relExpr.Range)) - // this is not correct JoinRelation but it is still binary operation - // we've already reported error now we can use operands of binary operation as join components - let l = wrapInArbErrSequence l "_keySelector1" - let r = wrapInArbErrSequence r "_keySelector2" - mkJoinExpr l r secondSourceSimplePats, varSpaceWithGroupJoinVars - | _ -> - errorR(Error(FSComp.SR.tcInvalidRelationInJoin(nm.idText), relExpr.Range)) - // since the shape of relExpr doesn't match our expectations (JoinRelation) - // then we assume that this is l.h.s. of the join relation - // so typechecker will treat relExpr as body of outerKeySelector lambda parameter in Join method - mkJoinExpr relExpr (arbExpr("_keySelector2", relExpr.Range)) secondSourceSimplePats, varSpaceWithGroupJoinVars - - | None, None when customOperationIsLikeZip nm -> - mkZipExpr, varSpaceWithSecondVars - - | _ -> - assert false - failwith "unreachable" - - - // Case from C# spec: A query expression with a join clause with an into followed by something other than a select clause - // Case from C# spec: A query expression with a join clause without an into followed by something other than a select clause - let valsInner, _env = varSpaceInner.Force mOpCore - let varSpaceExpr = mkExprForVarSpace mOpCore valsInner - let varSpacePat = mkPatForVarSpace mOpCore valsInner - let joinExpr = mkOverallExprGivenVarSpaceExpr varSpaceExpr - let consumingExpr = SynExpr.ForEach (DebugPointAtFor.No, DebugPointAtInOrTo.No, SeqExprOnly false, false, varSpacePat, joinExpr, innerComp, mOpCore) - Some (trans CompExprTranslationPass.Initial q varSpaceInner consumingExpr translatedCtxt) - - | SynExpr.ForEach (spFor, spIn, SeqExprOnly _seqExprOnly, isFromSource, pat, sourceExpr, innerComp, _mEntireForEach) -> - let sourceExpr = - match RewriteRangeExpr sourceExpr with - | Some e -> e - | None -> sourceExpr - let wrappedSourceExpr = mkSourceExprConditional isFromSource sourceExpr + let varSpaceWithGroupJoinVars = + match secondResultPatOpt with + | Some pat3 -> + addVarsToVarSpace varSpaceWithFirstVars (fun _mCustomOp env -> + use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - let mFor = - match spFor with - | DebugPointAtFor.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.For) - | DebugPointAtFor.No -> pat.Range + let _, _, vspecs, envinner, _ = + TcMatchPattern cenv (NewInferenceType g) env tpenv pat3 None - // For computation expressions, 'in' or 'to' is hit on each MoveNext. - // To support this a named debug point for the "in" keyword is available to inlined code. - match spIn with - | DebugPointAtInOrTo.Yes mIn -> - cenv.namedDebugPointsForInlinedCode[{Range=mFor; Name="ForLoop.InOrToKeyword"}] <- mIn - | _ -> () + vspecs, envinner) + | None -> varSpace + + let firstSourceSimplePats, later1 = + SimplePatsOfPat cenv.synArgNameGenerator firstSourcePat + + let secondSourceSimplePats, later2 = + SimplePatsOfPat cenv.synArgNameGenerator secondSourcePat + + if Option.isSome later1 then + errorR (Error(FSComp.SR.tcJoinMustUseSimplePattern (nm.idText), firstSourcePat.Range)) + + if Option.isSome later2 then + errorR (Error(FSComp.SR.tcJoinMustUseSimplePattern (nm.idText), secondSourcePat.Range)) + + // check 'join' or 'groupJoin' or 'zip' is permitted for this builder + match tryGetDataForCustomOperation nm with + | None -> error (Error(FSComp.SR.tcMissingCustomOperation (nm.idText), nm.idRange)) + | Some opDatas -> + let opName, _, _, _, _, _, _, _, methInfo = opDatas[0] + + // Record the resolution of the custom operation for posterity + let item = + Item.CustomOperation(opName, (fun () -> customOpUsageText nm), Some methInfo) + + // FUTURE: consider whether we can do better than emptyTyparInst here, in order to display instantiations + // of type variables in the quick info provided in the IDE. + CallNameResolutionSink cenv.tcSink (nm.idRange, env.NameEnv, item, emptyTyparInst, ItemOccurence.Use, env.eAccessRights) + + let mkJoinExpr keySelector1 keySelector2 innerPat e = + let mSynthetic = mOpCore.MakeSynthetic() + + mkSynCall + methInfo.DisplayName + mOpCore + [ + firstSource + secondSource + mkSynLambda firstSourceSimplePats keySelector1 mSynthetic + mkSynLambda secondSourceSimplePats keySelector2 mSynthetic + mkSynLambda firstSourceSimplePats (mkSynLambda innerPat e mSynthetic) mSynthetic + ] + + let mkZipExpr e = + let mSynthetic = mOpCore.MakeSynthetic() + + mkSynCall + methInfo.DisplayName + mOpCore + [ + firstSource + secondSource + mkSynLambda firstSourceSimplePats (mkSynLambda secondSourceSimplePats e mSynthetic) mSynthetic + ] + + // wraps given expression into sequence with result produced by arbExpr so result will look like: + // l; SynExpr.ArbitraryAfterError (...) + // this allows to handle cases like 'on (a > b)' // '>' is not permitted as correct join relation + // after wrapping a and b can still be typechecked (so we'll have correct completion inside 'on' part) + // but presence of SynExpr.ArbitraryAfterError allows to avoid errors about incompatible types in cases like + // query { + // for a in [1] do + // join b in [""] on (a > b) + // } + // if we typecheck raw 'a' and 'b' then we'll end up with 2 errors: + // 1. incorrect join relation + // 2. incompatible types: int and string + // with SynExpr.ArbitraryAfterError we have only first one + let wrapInArbErrSequence l caption = + SynExpr.Sequential(DebugPointAtSequential.SuppressNeither, true, l, (arbExpr (caption, l.Range.EndRange)), l.Range) + + let mkOverallExprGivenVarSpaceExpr, varSpaceInner = + + let isNullableOp opId = + match ConvertValLogicalNameToDisplayNameCore opId with + | "?=" + | "=?" + | "?=?" -> true + | _ -> false + + match secondResultPatOpt, keySelectorsOpt with + // groupJoin + | Some secondResultPat, Some relExpr when customOperationIsLikeGroupJoin nm -> + let secondResultSimplePats, later3 = + SimplePatsOfPat cenv.synArgNameGenerator secondResultPat + + if Option.isSome later3 then + errorR (Error(FSComp.SR.tcJoinMustUseSimplePattern (nm.idText), secondResultPat.Range)) + + match relExpr with + | JoinRelation cenv env (keySelector1, keySelector2) -> + mkJoinExpr keySelector1 keySelector2 secondResultSimplePats, varSpaceWithGroupJoinVars + | BinOpExpr(opId, l, r) -> + if isNullableOp opId.idText then + // When we cannot resolve NullableOps, recommend the relevant namespace to be added + errorR ( + Error( + FSComp.SR.cannotResolveNullableOperators (ConvertValLogicalNameToDisplayNameCore opId.idText), + relExpr.Range + ) + ) + else + errorR (Error(FSComp.SR.tcInvalidRelationInJoin (nm.idText), relExpr.Range)) + + let l = wrapInArbErrSequence l "_keySelector1" + let r = wrapInArbErrSequence r "_keySelector2" + // this is not correct JoinRelation but it is still binary operation + // we've already reported error now we can use operands of binary operation as join components + mkJoinExpr l r secondResultSimplePats, varSpaceWithGroupJoinVars + | _ -> + errorR (Error(FSComp.SR.tcInvalidRelationInJoin (nm.idText), relExpr.Range)) + // since the shape of relExpr doesn't match our expectations (JoinRelation) + // then we assume that this is l.h.s. of the join relation + // so typechecker will treat relExpr as body of outerKeySelector lambda parameter in GroupJoin method + mkJoinExpr relExpr (arbExpr ("_keySelector2", relExpr.Range)) secondResultSimplePats, + varSpaceWithGroupJoinVars + + | None, Some relExpr when customOperationIsLikeJoin nm -> + match relExpr with + | JoinRelation cenv env (keySelector1, keySelector2) -> + mkJoinExpr keySelector1 keySelector2 secondSourceSimplePats, varSpaceWithSecondVars + | BinOpExpr(opId, l, r) -> + if isNullableOp opId.idText then + // When we cannot resolve NullableOps, recommend the relevant namespace to be added + errorR ( + Error( + FSComp.SR.cannotResolveNullableOperators (ConvertValLogicalNameToDisplayNameCore opId.idText), + relExpr.Range + ) + ) + else + errorR (Error(FSComp.SR.tcInvalidRelationInJoin (nm.idText), relExpr.Range)) + // this is not correct JoinRelation but it is still binary operation + // we've already reported error now we can use operands of binary operation as join components + let l = wrapInArbErrSequence l "_keySelector1" + let r = wrapInArbErrSequence r "_keySelector2" + mkJoinExpr l r secondSourceSimplePats, varSpaceWithGroupJoinVars + | _ -> + errorR (Error(FSComp.SR.tcInvalidRelationInJoin (nm.idText), relExpr.Range)) + // since the shape of relExpr doesn't match our expectations (JoinRelation) + // then we assume that this is l.h.s. of the join relation + // so typechecker will treat relExpr as body of outerKeySelector lambda parameter in Join method + mkJoinExpr relExpr (arbExpr ("_keySelector2", relExpr.Range)) secondSourceSimplePats, + varSpaceWithGroupJoinVars + + | None, None when customOperationIsLikeZip nm -> mkZipExpr, varSpaceWithSecondVars + + | _ -> + assert false + failwith "unreachable" + + // Case from C# spec: A query expression with a join clause with an into followed by something other than a select clause + // Case from C# spec: A query expression with a join clause without an into followed by something other than a select clause + let valsInner, _env = varSpaceInner.Force mOpCore + let varSpaceExpr = mkExprForVarSpace mOpCore valsInner + let varSpacePat = mkPatForVarSpace mOpCore valsInner + let joinExpr = mkOverallExprGivenVarSpaceExpr varSpaceExpr + + let consumingExpr = + SynExpr.ForEach( + DebugPointAtFor.No, + DebugPointAtInOrTo.No, + SeqExprOnly false, + false, + varSpacePat, + joinExpr, + innerComp, + mOpCore + ) + + Some(trans CompExprTranslationPass.Initial q varSpaceInner consumingExpr translatedCtxt) + + | SynExpr.ForEach(spFor, spIn, SeqExprOnly _seqExprOnly, isFromSource, pat, sourceExpr, innerComp, _mEntireForEach) -> + let sourceExpr = + match RewriteRangeExpr sourceExpr with + | Some e -> e + | None -> sourceExpr + + let wrappedSourceExpr = mkSourceExprConditional isFromSource sourceExpr + + let mFor = + match spFor with + | DebugPointAtFor.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.For) + | DebugPointAtFor.No -> pat.Range + + // For computation expressions, 'in' or 'to' is hit on each MoveNext. + // To support this a named debug point for the "in" keyword is available to inlined code. + match spIn with + | DebugPointAtInOrTo.Yes mIn -> + cenv.namedDebugPointsForInlinedCode[{ + Range = mFor + Name = "ForLoop.InOrToKeyword" + }] <- mIn + | _ -> () + + let mPat = pat.Range + + if + isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mFor ad "For" builderTy) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("For"), mFor)) - let mPat = pat.Range + // Add the variables to the query variable space, on demand + let varSpace = + addVarsToVarSpace varSpace (fun _mCustomOp env -> + use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mFor ad "For" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("For"), mFor)) + let _, _, vspecs, envinner, _ = + TcMatchPattern cenv (NewInferenceType g) env tpenv pat None - // Add the variables to the query variable space, on demand - let varSpace = - addVarsToVarSpace varSpace (fun _mCustomOp env -> - use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType g) env tpenv pat None - vspecs, envinner) + vspecs, envinner) - Some (trans CompExprTranslationPass.Initial q varSpace innerComp - (fun innerCompR -> + Some( + trans CompExprTranslationPass.Initial q varSpace innerComp (fun innerCompR -> - let forCall = - mkSynCall "For" mFor [wrappedSourceExpr; SynExpr.MatchLambda (false, mPat, [SynMatchClause(pat, None, innerCompR, mPat, DebugPointAtTarget.Yes, SynMatchClauseTrivia.Zero)], DebugPointAtBinding.NoneAtInvisible, mFor) ] + let forCall = + mkSynCall + "For" + mFor + [ + wrappedSourceExpr + SynExpr.MatchLambda( + false, + mPat, + [ + SynMatchClause(pat, None, innerCompR, mPat, DebugPointAtTarget.Yes, SynMatchClauseTrivia.Zero) + ], + DebugPointAtBinding.NoneAtInvisible, + mFor + ) + ] let forCall = match spFor with - | DebugPointAtFor.Yes _ -> - SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mFor, false, forCall) + | DebugPointAtFor.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mFor, false, forCall) | DebugPointAtFor.No -> forCall - translatedCtxt forCall)) - - | SynExpr.For (forDebugPoint=spFor; toDebugPoint=spTo; ident=id; identBody=start; direction=dir; toBody=finish; doBody=innerComp; range=m) -> - let mFor = match spFor with DebugPointAtFor.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.For) | _ -> m - - if isQuery then errorR(Error(FSComp.SR.tcNoIntegerForLoopInQuery(), mFor)) - - let reduced = elimFastIntegerForLoop (spFor, spTo, id, start, dir, finish, innerComp, m) - Some (trans CompExprTranslationPass.Initial q varSpace reduced translatedCtxt ) - - | SynExpr.While (spWhile, guardExpr, innerComp, _) -> - let mGuard = guardExpr.Range - let mWhile = match spWhile with DebugPointAtWhile.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.While) | _ -> mGuard - - if isQuery then error(Error(FSComp.SR.tcNoWhileInQuery(), mWhile)) + translatedCtxt forCall) + ) + + | SynExpr.For( + forDebugPoint = spFor + toDebugPoint = spTo + ident = id + identBody = start + direction = dir + toBody = finish + doBody = innerComp + range = m) -> + let mFor = + match spFor with + | DebugPointAtFor.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.For) + | _ -> m + + if isQuery then + errorR (Error(FSComp.SR.tcNoIntegerForLoopInQuery (), mFor)) + + let reduced = + elimFastIntegerForLoop (spFor, spTo, id, start, dir, finish, innerComp, m) + + Some(trans CompExprTranslationPass.Initial q varSpace reduced translatedCtxt) + + | SynExpr.While(spWhile, guardExpr, innerComp, _) -> + let mGuard = guardExpr.Range + + let mWhile = + match spWhile with + | DebugPointAtWhile.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.While) + | _ -> mGuard + + if isQuery then + error (Error(FSComp.SR.tcNoWhileInQuery (), mWhile)) + + if + isNil ( + TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mWhile ad "While" builderTy + ) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("While"), mWhile)) + + if + isNil ( + TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mWhile ad "Delay" builderTy + ) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("Delay"), mWhile)) + + // 'while' is hit just before each time the guard is called + let guardExpr = + match spWhile with + | DebugPointAtWhile.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mWhile, false, guardExpr) + | DebugPointAtWhile.No -> guardExpr + + Some( + trans CompExprTranslationPass.Initial q varSpace innerComp (fun holeFill -> + translatedCtxt ( + mkSynCall + "While" + mWhile + [ + mkSynDelay2 guardExpr + mkSynCall "Delay" mWhile [ mkSynDelay innerComp.Range holeFill ] + ] + )) + ) + + | SynExpr.WhileBang(spWhile, guardExpr, innerComp, mOrig) -> + let mGuard = guardExpr.Range + + let mWhile = + match spWhile with + | DebugPointAtWhile.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.While) + | _ -> mGuard + + let mGuard = mGuard.MakeSynthetic() + + // 'while!' is hit just before each time the guard is called + let guardExpr = + match spWhile with + | DebugPointAtWhile.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mWhile, false, guardExpr) + | DebugPointAtWhile.No -> guardExpr + + let rewrittenWhileExpr = + let idFirst = mkSynId mGuard (CompilerGeneratedName "first") + let patFirst = mkSynPatVar None idFirst + + let body = + let idCond = mkSynId mGuard (CompilerGeneratedName "cond") + let patCond = mkSynPatVar None idCond + + let condBinding = + mkSynBinding + (Xml.PreXmlDoc.Empty, patCond) + (None, + false, + true, + mGuard, + DebugPointAtBinding.NoneAtSticky, + None, + SynExpr.Ident idFirst, + mGuard, + [], + [], + None, + SynBindingTrivia.Zero) + + let setCondExpr = SynExpr.Set(SynExpr.Ident idCond, SynExpr.Ident idFirst, mGuard) + + let bindCondExpr = + SynExpr.LetOrUseBang( + DebugPointAtBinding.NoneAtSticky, + false, + true, + patFirst, + guardExpr, + [], + setCondExpr, + mGuard, + SynExprLetOrUseBangTrivia.Zero + ) + + let whileExpr = + SynExpr.While( + DebugPointAtWhile.No, + SynExpr.Ident idCond, + SynExpr.Sequential(DebugPointAtSequential.SuppressBoth, true, innerComp, bindCondExpr, mWhile), + mOrig + ) + + SynExpr.LetOrUse(false, false, [ condBinding ], whileExpr, mGuard, SynExprLetOrUseTrivia.Zero) + + SynExpr.LetOrUseBang( + DebugPointAtBinding.NoneAtSticky, + false, + true, + patFirst, + guardExpr, + [], + body, + mGuard, + SynExprLetOrUseBangTrivia.Zero + ) + + tryTrans CompExprTranslationPass.Initial q varSpace rewrittenWhileExpr translatedCtxt + + | SynExpr.TryFinally(innerComp, unwindExpr, _mTryToLast, spTry, spFinally, trivia) -> + + let mTry = + match spTry with + | DebugPointAtTry.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.Try) + | _ -> trivia.TryKeyword + + let mFinally = + match spFinally with + | DebugPointAtFinally.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.Finally) + | _ -> trivia.FinallyKeyword + + // Put down a debug point for the 'finally' + let unwindExpr2 = + match spFinally with + | DebugPointAtFinally.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mFinally, true, unwindExpr) + | DebugPointAtFinally.No -> unwindExpr + + if isQuery then + error (Error(FSComp.SR.tcNoTryFinallyInQuery (), mTry)) + + if + isNil ( + TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "TryFinally" builderTy + ) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("TryFinally"), mTry)) + + if + isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "Delay" builderTy) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("Delay"), mTry)) + + let innerExpr = transNoQueryOps innerComp + + let innerExpr = + match spTry with + | DebugPointAtTry.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mTry, true, innerExpr) + | _ -> innerExpr + + Some( + translatedCtxt ( + mkSynCall + "TryFinally" + mTry + [ + mkSynCall "Delay" mTry [ mkSynDelay innerComp.Range innerExpr ] + mkSynDelay2 unwindExpr2 + ] + ) + ) + + | SynExpr.Paren(range = m) -> error (Error(FSComp.SR.tcConstructIsAmbiguousInComputationExpression (), m)) + + // In some cases the node produced by `mkSynCall "Zero" m []` may be discarded in the case + // of implicit yields - for example "list { 1; 2 }" when each expression checks as an implicit yield. + // If it is not discarded, the syntax node will later be checked and the existence/non-existence of the Zero method + // will be checked/reported appropriately (though the error message won't mention computation expressions + // like our other error messages for missing methods). + | SynExpr.ImplicitZero m -> + if + (not enableImplicitYield) + && isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Zero" builderTy) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("Zero"), m)) + + Some(translatedCtxt (mkSynCall "Zero" m [])) + + | OptionalSequential(JoinOrGroupJoinOrZipClause(_, _, _, _, _, mClause), _) when firstTry = CompExprTranslationPass.Initial -> + + // 'join' clauses preceded by 'let' and other constructs get processed by repackaging with a 'for' loop. + let patvs, _env = varSpace.Force comp.Range + let varSpaceExpr = mkExprForVarSpace mClause patvs + let varSpacePat = mkPatForVarSpace mClause patvs + + let dataCompPrior = + translatedCtxt (transNoQueryOps (SynExpr.YieldOrReturn((true, false), varSpaceExpr, mClause))) + + // Rebind using for ... + let rebind = + SynExpr.ForEach( + DebugPointAtFor.No, + DebugPointAtInOrTo.No, + SeqExprOnly false, + false, + varSpacePat, + dataCompPrior, + comp, + comp.Range + ) + + // Retry with the 'for' loop packaging. Set firstTry=false just in case 'join' processing fails + tryTrans CompExprTranslationPass.Subsequent q varSpace rebind id + + | OptionalSequential(CustomOperationClause(nm, _, opExpr, mClause, _), _) -> + + if q = CustomOperationsMode.Denied then + error (Error(FSComp.SR.tcCustomOperationMayNotBeUsedHere (), opExpr.Range)) + + let patvs, _env = varSpace.Force comp.Range + let varSpaceExpr = mkExprForVarSpace mClause patvs + + let dataCompPriorToOp = + let isYield = not (customOperationMaintainsVarSpaceUsingBind nm) + translatedCtxt (transNoQueryOps (SynExpr.YieldOrReturn((isYield, false), varSpaceExpr, mClause))) + + // Now run the consumeCustomOpClauses + Some(consumeCustomOpClauses q varSpace dataCompPriorToOp comp false mClause) + + | SynExpr.Sequential(sp, true, innerComp1, innerComp2, m) -> + + // Check for 'where x > y' and other mis-applications of infix operators. If detected, give a good error message, and just ignore innerComp1 + if isQuery && checkForBinaryApp innerComp1 then + Some(trans CompExprTranslationPass.Initial q varSpace innerComp2 translatedCtxt) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mWhile ad "While" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("While"), mWhile)) - - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mWhile ad "Delay" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mWhile)) - - // 'while' is hit just before each time the guard is called - let guardExpr = - match spWhile with - | DebugPointAtWhile.Yes _ -> - SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mWhile, false, guardExpr) - | DebugPointAtWhile.No -> guardExpr - - Some(trans CompExprTranslationPass.Initial q varSpace innerComp (fun holeFill -> - translatedCtxt - (mkSynCall "While" mWhile - [ mkSynDelay2 guardExpr; - mkSynCall "Delay" mWhile [mkSynDelay innerComp.Range holeFill]])) ) - - | SynExpr.WhileBang (spWhile, guardExpr, innerComp, mOrig) -> - let mGuard = guardExpr.Range - let mWhile = match spWhile with DebugPointAtWhile.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.While) | _ -> mGuard - let mGuard = mGuard.MakeSynthetic() - - // 'while!' is hit just before each time the guard is called - let guardExpr = - match spWhile with - | DebugPointAtWhile.Yes _ -> - SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mWhile, false, guardExpr) - | DebugPointAtWhile.No -> guardExpr - - let rewrittenWhileExpr = - let idFirst = mkSynId mGuard (CompilerGeneratedName "first") - let patFirst = mkSynPatVar None idFirst - - let body = - let idCond = mkSynId mGuard (CompilerGeneratedName "cond") - let patCond = mkSynPatVar None idCond - let condBinding = mkSynBinding (Xml.PreXmlDoc.Empty, patCond) (None, false, true, mGuard, DebugPointAtBinding.NoneAtSticky, None, SynExpr.Ident idFirst, mGuard, [], [], None, SynBindingTrivia.Zero) - let setCondExpr = SynExpr.Set (SynExpr.Ident idCond, SynExpr.Ident idFirst, mGuard) - let bindCondExpr = SynExpr.LetOrUseBang (DebugPointAtBinding.NoneAtSticky, false, true, patFirst, guardExpr, [], setCondExpr, mGuard, SynExprLetOrUseBangTrivia.Zero) - - let whileExpr = SynExpr.While (DebugPointAtWhile.No, SynExpr.Ident idCond, SynExpr.Sequential (DebugPointAtSequential.SuppressBoth, true, innerComp, bindCondExpr, mWhile), mOrig) - SynExpr.LetOrUse (false, false, [ condBinding ], whileExpr, mGuard, SynExprLetOrUseTrivia.Zero) - - SynExpr.LetOrUseBang (DebugPointAtBinding.NoneAtSticky, false, true, patFirst, guardExpr, [], body, mGuard, SynExprLetOrUseBangTrivia.Zero) - - tryTrans CompExprTranslationPass.Initial q varSpace rewrittenWhileExpr translatedCtxt - - | SynExpr.TryFinally (innerComp, unwindExpr, _mTryToLast, spTry, spFinally, trivia) -> - - let mTry = match spTry with DebugPointAtTry.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.Try) | _ -> trivia.TryKeyword - let mFinally = match spFinally with DebugPointAtFinally.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.Finally) | _ -> trivia.FinallyKeyword - - // Put down a debug point for the 'finally' - let unwindExpr2 = - match spFinally with - | DebugPointAtFinally.Yes _ -> - SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mFinally, true, unwindExpr) - | DebugPointAtFinally.No -> unwindExpr - - if isQuery then error(Error(FSComp.SR.tcNoTryFinallyInQuery(), mTry)) - - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "TryFinally" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("TryFinally"), mTry)) - - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "Delay" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mTry)) - - let innerExpr = transNoQueryOps innerComp - - let innerExpr = - match spTry with - | DebugPointAtTry.Yes _ -> - SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mTry, true, innerExpr) - | _ -> innerExpr - - Some (translatedCtxt - (mkSynCall "TryFinally" mTry [ - mkSynCall "Delay" mTry [mkSynDelay innerComp.Range innerExpr] - mkSynDelay2 unwindExpr2])) - - | SynExpr.Paren (_, _, _, m) -> - error(Error(FSComp.SR.tcConstructIsAmbiguousInComputationExpression(), m)) - - // In some cases the node produced by `mkSynCall "Zero" m []` may be discarded in the case - // of implicit yields - for example "list { 1; 2 }" when each expression checks as an implicit yield. - // If it is not discarded, the syntax node will later be checked and the existence/non-existence of the Zero method - // will be checked/reported appropriately (though the error message won't mention computation expressions - // like our other error messages for missing methods). - | SynExpr.ImplicitZero m -> - if (not enableImplicitYield) && - isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Zero" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("Zero"), m)) - Some (translatedCtxt (mkSynCall "Zero" m [])) - - | OptionalSequential (JoinOrGroupJoinOrZipClause (_, _, _, _, _, mClause), _) - when firstTry = CompExprTranslationPass.Initial -> - - // 'join' clauses preceded by 'let' and other constructs get processed by repackaging with a 'for' loop. - let patvs, _env = varSpace.Force comp.Range - let varSpaceExpr = mkExprForVarSpace mClause patvs - let varSpacePat = mkPatForVarSpace mClause patvs - - let dataCompPrior = - translatedCtxt (transNoQueryOps (SynExpr.YieldOrReturn ((true, false), varSpaceExpr, mClause))) - - // Rebind using for ... - let rebind = - SynExpr.ForEach (DebugPointAtFor.No, DebugPointAtInOrTo.No, SeqExprOnly false, false, varSpacePat, dataCompPrior, comp, comp.Range) - - // Retry with the 'for' loop packaging. Set firstTry=false just in case 'join' processing fails - tryTrans CompExprTranslationPass.Subsequent q varSpace rebind id + else + if isQuery && not (innerComp1.IsArbExprAndThusAlreadyReportedError) then + match innerComp1 with + | SynExpr.JoinIn _ -> () // an error will be reported later when we process innerComp1 as a sequential + | _ -> errorR (Error(FSComp.SR.tcUnrecognizedQueryOperator (), innerComp1.RangeOfFirstPortion)) + + match tryTrans CompExprTranslationPass.Initial CustomOperationsMode.Denied varSpace innerComp1 id with + | Some c -> + // "cexpr; cexpr" is treated as builder.Combine(cexpr1, cexpr1) + let m1 = rangeForCombine innerComp1 + + if + isNil ( + TryFindIntrinsicOrExtensionMethInfo + ResultCollectionSettings.AtMostOneResult + cenv + env + m + ad + "Combine" + builderTy + ) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("Combine"), m)) + + if + isNil ( + TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Delay" builderTy + ) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("Delay"), m)) + + let combineCall = + mkSynCall + "Combine" + m1 + [ + c + mkSynCall "Delay" m1 [ mkSynDelay innerComp2.Range (transNoQueryOps innerComp2) ] + ] + + Some(translatedCtxt combineCall) + + | None -> + // "do! expr; cexpr" is treated as { let! () = expr in cexpr } + match innerComp1 with + | SynExpr.DoBang(rhsExpr, m) -> + let sp = + match sp with + | DebugPointAtSequential.SuppressExpr -> DebugPointAtBinding.NoneAtDo + | DebugPointAtSequential.SuppressBoth -> DebugPointAtBinding.NoneAtDo + | DebugPointAtSequential.SuppressStmt -> DebugPointAtBinding.Yes m + | DebugPointAtSequential.SuppressNeither -> DebugPointAtBinding.Yes m + + Some( + trans + CompExprTranslationPass.Initial + q + varSpace + (SynExpr.LetOrUseBang( + sp, + false, + true, + SynPat.Const(SynConst.Unit, rhsExpr.Range), + rhsExpr, + [], + innerComp2, + m, + SynExprLetOrUseBangTrivia.Zero + )) + translatedCtxt + ) + + // "expr; cexpr" is treated as sequential execution + | _ -> + Some( + trans CompExprTranslationPass.Initial q varSpace innerComp2 (fun holeFill -> + let fillExpr = + if enableImplicitYield then + // When implicit yields are enabled, then if the 'innerComp1' checks as type + // 'unit' we interpret the expression as a sequential, and when it doesn't + // have type 'unit' we interpret it as a 'Yield + Combine'. + let combineExpr = + let m1 = rangeForCombine innerComp1 + let implicitYieldExpr = mkSynCall "Yield" comp.Range [ innerComp1 ] + + mkSynCall + "Combine" + m1 + [ + implicitYieldExpr + mkSynCall "Delay" m1 [ mkSynDelay holeFill.Range holeFill ] + ] + + SynExpr.SequentialOrImplicitYield(sp, innerComp1, holeFill, combineExpr, m) + else + SynExpr.Sequential(sp, true, innerComp1, holeFill, m) + + translatedCtxt fillExpr) + ) + + | SynExpr.IfThenElse(guardExpr, thenComp, elseCompOpt, spIfToThen, isRecovery, mIfToEndOfElseBranch, trivia) -> + match elseCompOpt with + | Some elseComp -> + if isQuery then + error (Error(FSComp.SR.tcIfThenElseMayNotBeUsedWithinQueries (), trivia.IfToThenRange)) + + Some( + translatedCtxt ( + SynExpr.IfThenElse( + guardExpr, + transNoQueryOps thenComp, + Some(transNoQueryOps elseComp), + spIfToThen, + isRecovery, + mIfToEndOfElseBranch, + trivia + ) + ) + ) + | None -> + let elseComp = + if + isNil ( + TryFindIntrinsicOrExtensionMethInfo + ResultCollectionSettings.AtMostOneResult + cenv + env + trivia.IfToThenRange + ad + "Zero" + builderTy + ) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("Zero"), trivia.IfToThenRange)) + + mkSynCall "Zero" trivia.IfToThenRange [] + + Some( + trans CompExprTranslationPass.Initial q varSpace thenComp (fun holeFill -> + translatedCtxt ( + SynExpr.IfThenElse( + guardExpr, + holeFill, + Some elseComp, + spIfToThen, + isRecovery, + mIfToEndOfElseBranch, + trivia + ) + )) + ) + + // 'let binds in expr' + | SynExpr.LetOrUse(isRec, false, binds, innerComp, m, trivia) -> + + // For 'query' check immediately + if isQuery then + match (List.map (BindingNormalization.NormalizeBinding ValOrMemberBinding cenv env) binds) with + | [ NormalizedBinding(_, SynBindingKind.Normal, false, false, _, _, _, _, _, _, _, _) ] when not isRec -> () + | normalizedBindings -> + let failAt m = + error (Error(FSComp.SR.tcNonSimpleLetBindingInQuery (), m)) + + match normalizedBindings with + | NormalizedBinding(mBinding = mBinding) :: _ -> failAt mBinding + | _ -> failAt m - | OptionalSequential (CustomOperationClause (nm, _, opExpr, mClause, _), _) -> + // Add the variables to the query variable space, on demand + let varSpace = + addVarsToVarSpace varSpace (fun mQueryOp env -> + // Normalize the bindings before detecting the bound variables + match (List.map (BindingNormalization.NormalizeBinding ValOrMemberBinding cenv env) binds) with + | [ NormalizedBinding(kind = SynBindingKind.Normal; mustInline = false; isMutable = false; pat = pat) ] -> + // successful case + use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - if q = CustomOperationsMode.Denied then error(Error(FSComp.SR.tcCustomOperationMayNotBeUsedHere(), opExpr.Range)) + let _, _, vspecs, envinner, _ = + TcMatchPattern cenv (NewInferenceType g) env tpenv pat None + + vspecs, envinner + | _ -> + // error case + error (Error(FSComp.SR.tcCustomOperationMayNotBeUsedInConjunctionWithNonSimpleLetBindings (), mQueryOp))) + + Some( + trans CompExprTranslationPass.Initial q varSpace innerComp (fun holeFill -> + translatedCtxt (SynExpr.LetOrUse(isRec, false, binds, holeFill, m, trivia))) + ) + + // 'use x = expr in expr' + | SynExpr.LetOrUse( + isUse = true + bindings = [ SynBinding(kind = SynBindingKind.Normal; headPat = pat; expr = rhsExpr; debugPoint = spBind) ] + body = innerComp) -> + let mBind = + match spBind with + | DebugPointAtBinding.Yes m -> m + | _ -> rhsExpr.Range + + if isQuery then + error (Error(FSComp.SR.tcUseMayNotBeUsedInQueries (), mBind)) + + let innerCompRange = innerComp.Range + + let consumeExpr = + SynExpr.MatchLambda( + false, + innerCompRange, + [ + SynMatchClause( + pat, + None, + transNoQueryOps innerComp, + innerCompRange, + DebugPointAtTarget.Yes, + SynMatchClauseTrivia.Zero + ) + ], + DebugPointAtBinding.NoneAtInvisible, + innerCompRange + ) + + if + isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBind ad "Using" builderTy) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("Using"), mBind)) + + Some( + translatedCtxt (mkSynCall "Using" mBind [ rhsExpr; consumeExpr ]) + |> addBindDebugPoint spBind + ) + + // 'let! pat = expr in expr' + // --> build.Bind(e1, (fun _argN -> match _argN with pat -> expr)) + // or + // --> build.BindReturn(e1, (fun _argN -> match _argN with pat -> expr-without-return)) + | SynExpr.LetOrUseBang( + bindDebugPoint = spBind + isUse = false + isFromSource = isFromSource + pat = pat + rhs = rhsExpr + andBangs = [] + body = innerComp) -> + + let mBind = + match spBind with + | DebugPointAtBinding.Yes m -> m + | _ -> rhsExpr.Range + + if isQuery then + error (Error(FSComp.SR.tcBindMayNotBeUsedInQueries (), mBind)) - let patvs, _env = varSpace.Force comp.Range - let varSpaceExpr = mkExprForVarSpace mClause patvs - - let dataCompPriorToOp = - let isYield = not (customOperationMaintainsVarSpaceUsingBind nm) - translatedCtxt (transNoQueryOps (SynExpr.YieldOrReturn ((isYield, false), varSpaceExpr, mClause))) - - // Now run the consumeCustomOpClauses - Some (consumeCustomOpClauses q varSpace dataCompPriorToOp comp false mClause) - - | SynExpr.Sequential (sp, true, innerComp1, innerComp2, m) -> - - // Check for 'where x > y' and other mis-applications of infix operators. If detected, give a good error message, and just ignore innerComp1 - if isQuery && checkForBinaryApp innerComp1 then - Some (trans CompExprTranslationPass.Initial q varSpace innerComp2 translatedCtxt) - - else - - if isQuery && not(innerComp1.IsArbExprAndThusAlreadyReportedError) then - match innerComp1 with - | SynExpr.JoinIn _ -> () // an error will be reported later when we process innerComp1 as a sequential - | _ -> errorR(Error(FSComp.SR.tcUnrecognizedQueryOperator(), innerComp1.RangeOfFirstPortion)) - - match tryTrans CompExprTranslationPass.Initial CustomOperationsMode.Denied varSpace innerComp1 id with - | Some c -> - // "cexpr; cexpr" is treated as builder.Combine(cexpr1, cexpr1) - let m1 = rangeForCombine innerComp1 - - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Combine" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("Combine"), m)) - - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Delay" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), m)) - - let combineCall = mkSynCall "Combine" m1 [c; mkSynCall "Delay" m1 [mkSynDelay innerComp2.Range (transNoQueryOps innerComp2)]] - - Some (translatedCtxt combineCall) - - | None -> - // "do! expr; cexpr" is treated as { let! () = expr in cexpr } - match innerComp1 with - | SynExpr.DoBang (rhsExpr, m) -> - let sp = - match sp with - | DebugPointAtSequential.SuppressExpr -> DebugPointAtBinding.NoneAtDo - | DebugPointAtSequential.SuppressBoth -> DebugPointAtBinding.NoneAtDo - | DebugPointAtSequential.SuppressStmt -> DebugPointAtBinding.Yes m - | DebugPointAtSequential.SuppressNeither -> DebugPointAtBinding.Yes m - Some(trans CompExprTranslationPass.Initial q varSpace (SynExpr.LetOrUseBang (sp, false, true, SynPat.Const(SynConst.Unit, rhsExpr.Range), rhsExpr, [], innerComp2, m, SynExprLetOrUseBangTrivia.Zero)) translatedCtxt) - - // "expr; cexpr" is treated as sequential execution - | _ -> - Some (trans CompExprTranslationPass.Initial q varSpace innerComp2 (fun holeFill -> - let fillExpr = - if enableImplicitYield then - // When implicit yields are enabled, then if the 'innerComp1' checks as type - // 'unit' we interpret the expression as a sequential, and when it doesn't - // have type 'unit' we interpret it as a 'Yield + Combine'. - let combineExpr = - let m1 = rangeForCombine innerComp1 - let implicitYieldExpr = mkSynCall "Yield" comp.Range [innerComp1] - mkSynCall "Combine" m1 [implicitYieldExpr; mkSynCall "Delay" m1 [mkSynDelay holeFill.Range holeFill]] - SynExpr.SequentialOrImplicitYield(sp, innerComp1, holeFill, combineExpr, m) - else - SynExpr.Sequential(sp, true, innerComp1, holeFill, m) - translatedCtxt fillExpr)) - - | SynExpr.IfThenElse (guardExpr, thenComp, elseCompOpt, spIfToThen, isRecovery, mIfToEndOfElseBranch, trivia) -> - match elseCompOpt with - | Some elseComp -> - if isQuery then error(Error(FSComp.SR.tcIfThenElseMayNotBeUsedWithinQueries(), trivia.IfToThenRange)) - Some (translatedCtxt (SynExpr.IfThenElse (guardExpr, transNoQueryOps thenComp, Some(transNoQueryOps elseComp), spIfToThen, isRecovery, mIfToEndOfElseBranch, trivia))) - | None -> - let elseComp = - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env trivia.IfToThenRange ad "Zero" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("Zero"), trivia.IfToThenRange)) - mkSynCall "Zero" trivia.IfToThenRange [] - Some (trans CompExprTranslationPass.Initial q varSpace thenComp (fun holeFill -> translatedCtxt (SynExpr.IfThenElse (guardExpr, holeFill, Some elseComp, spIfToThen, isRecovery, mIfToEndOfElseBranch, trivia)))) - - // 'let binds in expr' - | SynExpr.LetOrUse (isRec, false, binds, innerComp, m, trivia) -> - - // For 'query' check immediately - if isQuery then - match (List.map (BindingNormalization.NormalizeBinding ValOrMemberBinding cenv env) binds) with - | [NormalizedBinding(_, SynBindingKind.Normal, false, false, _, _, _, _, _, _, _, _)] when not isRec -> - () - | normalizedBindings -> - let failAt m = error(Error(FSComp.SR.tcNonSimpleLetBindingInQuery(), m)) - match normalizedBindings with - | NormalizedBinding(_, _, _, _, _, _, _, _, _, _, mBinding, _) :: _ -> failAt mBinding - | _ -> failAt m - - // Add the variables to the query variable space, on demand - let varSpace = - addVarsToVarSpace varSpace (fun mQueryOp env -> - // Normalize the bindings before detecting the bound variables - match (List.map (BindingNormalization.NormalizeBinding ValOrMemberBinding cenv env) binds) with - | [NormalizedBinding(_vis, SynBindingKind.Normal, false, false, _, _, _, _, pat, _, _, _)] -> - // successful case + // Add the variables to the query variable space, on demand + let varSpace = + addVarsToVarSpace varSpace (fun _mCustomOp env -> use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType g) env tpenv pat None - vspecs, envinner - | _ -> - // error case - error(Error(FSComp.SR.tcCustomOperationMayNotBeUsedInConjunctionWithNonSimpleLetBindings(), mQueryOp))) - Some (trans CompExprTranslationPass.Initial q varSpace innerComp (fun holeFill -> translatedCtxt (SynExpr.LetOrUse (isRec, false, binds, holeFill, m, trivia)))) + let _, _, vspecs, envinner, _ = + TcMatchPattern cenv (NewInferenceType g) env tpenv pat None - // 'use x = expr in expr' - | SynExpr.LetOrUse (isUse=true; bindings=[SynBinding (kind=SynBindingKind.Normal; headPat=pat; expr=rhsExpr; debugPoint=spBind)]; body=innerComp) -> - let mBind = match spBind with DebugPointAtBinding.Yes m -> m | _ -> rhsExpr.Range - if isQuery then error(Error(FSComp.SR.tcUseMayNotBeUsedInQueries(), mBind)) - let innerCompRange = innerComp.Range - let consumeExpr = SynExpr.MatchLambda(false, innerCompRange, [SynMatchClause(pat, None, transNoQueryOps innerComp, innerCompRange, DebugPointAtTarget.Yes, SynMatchClauseTrivia.Zero)], DebugPointAtBinding.NoneAtInvisible, innerCompRange) - - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBind ad "Using" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("Using"), mBind)) - - Some (translatedCtxt (mkSynCall "Using" mBind [rhsExpr; consumeExpr ]) |> addBindDebugPoint spBind) - - // 'let! pat = expr in expr' - // --> build.Bind(e1, (fun _argN -> match _argN with pat -> expr)) - // or - // --> build.BindReturn(e1, (fun _argN -> match _argN with pat -> expr-without-return)) - | SynExpr.LetOrUseBang (bindDebugPoint=spBind; isUse=false; isFromSource=isFromSource; pat=pat; rhs=rhsExpr; andBangs=[]; body=innerComp) -> - - let mBind = match spBind with DebugPointAtBinding.Yes m -> m | _ -> rhsExpr.Range - if isQuery then error(Error(FSComp.SR.tcBindMayNotBeUsedInQueries(), mBind)) - - // Add the variables to the query variable space, on demand - let varSpace = - addVarsToVarSpace varSpace (fun _mCustomOp env -> - use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType g) env tpenv pat None vspecs, envinner) - let rhsExpr = mkSourceExprConditional isFromSource rhsExpr - Some (transBind q varSpace mBind (addBindDebugPoint spBind) "Bind" [rhsExpr] pat innerComp translatedCtxt) - - // 'use! pat = e1 in e2' --> build.Bind(e1, (function _argN -> match _argN with pat -> build.Using(x, (fun _argN -> match _argN with pat -> e2)))) - | SynExpr.LetOrUseBang (bindDebugPoint=spBind; isUse=true; isFromSource=isFromSource; pat=SynPat.Named (ident=SynIdent(id,_); isThisVal=false) as pat; rhs=rhsExpr; andBangs=[]; body=innerComp) - | SynExpr.LetOrUseBang (bindDebugPoint=spBind; isUse=true; isFromSource=isFromSource; pat=SynPat.LongIdent (longDotId=SynLongIdent([id], _, _)) as pat; rhs=rhsExpr; andBangs=[]; body=innerComp) -> - - let mBind = match spBind with DebugPointAtBinding.Yes m -> m | _ -> rhsExpr.Range - if isQuery then error(Error(FSComp.SR.tcBindMayNotBeUsedInQueries(), mBind)) - - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBind ad "Using" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("Using"), mBind)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBind ad "Bind" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("Bind"), mBind)) - - let bindExpr = - let consumeExpr = SynExpr.MatchLambda(false, mBind, [SynMatchClause(pat, None, transNoQueryOps innerComp, innerComp.Range, DebugPointAtTarget.Yes, SynMatchClauseTrivia.Zero)], DebugPointAtBinding.NoneAtInvisible, mBind) - let consumeExpr = mkSynCall "Using" mBind [SynExpr.Ident id; consumeExpr ] - let consumeExpr = SynExpr.MatchLambda(false, mBind, [SynMatchClause(pat, None, consumeExpr, id.idRange, DebugPointAtTarget.No, SynMatchClauseTrivia.Zero)], DebugPointAtBinding.NoneAtInvisible, mBind) let rhsExpr = mkSourceExprConditional isFromSource rhsExpr - mkSynCall "Bind" mBind [rhsExpr; consumeExpr] - |> addBindDebugPoint spBind + Some(transBind q varSpace mBind (addBindDebugPoint spBind) "Bind" [ rhsExpr ] pat innerComp translatedCtxt) + + // 'use! pat = e1 in e2' --> build.Bind(e1, (function _argN -> match _argN with pat -> build.Using(x, (fun _argN -> match _argN with pat -> e2)))) + | SynExpr.LetOrUseBang( + bindDebugPoint = spBind + isUse = true + isFromSource = isFromSource + pat = SynPat.Named(ident = SynIdent(id, _); isThisVal = false) as pat + rhs = rhsExpr + andBangs = [] + body = innerComp) + | SynExpr.LetOrUseBang( + bindDebugPoint = spBind + isUse = true + isFromSource = isFromSource + pat = SynPat.LongIdent(longDotId = SynLongIdent(id = [ id ])) as pat + rhs = rhsExpr + andBangs = [] + body = innerComp) -> + + let mBind = + match spBind with + | DebugPointAtBinding.Yes m -> m + | _ -> rhsExpr.Range + + if isQuery then + error (Error(FSComp.SR.tcBindMayNotBeUsedInQueries (), mBind)) + + if + isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBind ad "Using" builderTy) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("Using"), mBind)) + + if + isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBind ad "Bind" builderTy) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("Bind"), mBind)) + + let bindExpr = + let consumeExpr = + SynExpr.MatchLambda( + false, + mBind, + [ + SynMatchClause( + pat, + None, + transNoQueryOps innerComp, + innerComp.Range, + DebugPointAtTarget.Yes, + SynMatchClauseTrivia.Zero + ) + ], + DebugPointAtBinding.NoneAtInvisible, + mBind + ) + + let consumeExpr = mkSynCall "Using" mBind [ SynExpr.Ident id; consumeExpr ] + + let consumeExpr = + SynExpr.MatchLambda( + false, + mBind, + [ + SynMatchClause(pat, None, consumeExpr, id.idRange, DebugPointAtTarget.No, SynMatchClauseTrivia.Zero) + ], + DebugPointAtBinding.NoneAtInvisible, + mBind + ) + + let rhsExpr = mkSourceExprConditional isFromSource rhsExpr + mkSynCall "Bind" mBind [ rhsExpr; consumeExpr ] |> addBindDebugPoint spBind + + Some(translatedCtxt bindExpr) + + // 'use! pat = e1 ... in e2' where 'pat' is not a simple name --> error + | SynExpr.LetOrUseBang(isUse = true; pat = pat; andBangs = andBangs) -> + if isNil andBangs then + error (Error(FSComp.SR.tcInvalidUseBangBinding (), pat.Range)) + else + error (Error(FSComp.SR.tcInvalidUseBangBindingNoAndBangs (), comp.Range)) + + // 'let! pat1 = expr1 and! pat2 = expr2 in ...' --> + // build.BindN(expr1, expr2, ...) + // or + // build.BindNReturn(expr1, expr2, ...) + // or + // build.Bind(build.MergeSources(expr1, expr2), ...) + | SynExpr.LetOrUseBang( + bindDebugPoint = spBind + isUse = false + isFromSource = isFromSource + pat = letPat + rhs = letRhsExpr + andBangs = andBangBindings + body = innerComp + range = letBindRange) -> + if not (cenv.g.langVersion.SupportsFeature LanguageFeature.AndBang) then + error (Error(FSComp.SR.tcAndBangNotSupported (), comp.Range)) + + if isQuery then + error (Error(FSComp.SR.tcBindMayNotBeUsedInQueries (), letBindRange)) + + let mBind = + match spBind with + | DebugPointAtBinding.Yes m -> m + | _ -> letRhsExpr.Range + + let sources = + (letRhsExpr + :: [ for SynExprAndBang(body = andExpr) in andBangBindings -> andExpr ]) + |> List.map (mkSourceExprConditional isFromSource) + + let pats = + letPat :: [ for SynExprAndBang(pat = andPat) in andBangBindings -> andPat ] + + let sourcesRange = sources |> List.map (fun e -> e.Range) |> List.reduce unionRanges + + let numSources = sources.Length + let bindReturnNName = "Bind" + string numSources + "Return" + let bindNName = "Bind" + string numSources + + // Check if this is a Bind2Return etc. + let hasBindReturnN = + not ( + isNil ( + TryFindIntrinsicOrExtensionMethInfo + ResultCollectionSettings.AtMostOneResult + cenv + env + mBind + ad + bindReturnNName + builderTy + ) + ) + + if hasBindReturnN && Option.isSome (convertSimpleReturnToExpr varSpace innerComp) then + let consumePat = SynPat.Tuple(false, pats, [], letPat.Range) - Some(translatedCtxt bindExpr) + // Add the variables to the query variable space, on demand + let varSpace = + addVarsToVarSpace varSpace (fun _mCustomOp env -> + use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - // 'use! pat = e1 ... in e2' where 'pat' is not a simple name --> error - | SynExpr.LetOrUseBang (isUse=true; pat=pat; andBangs=andBangs) -> - if isNil andBangs then - error(Error(FSComp.SR.tcInvalidUseBangBinding(), pat.Range)) - else - error(Error(FSComp.SR.tcInvalidUseBangBindingNoAndBangs(), comp.Range)) - - // 'let! pat1 = expr1 and! pat2 = expr2 in ...' --> - // build.BindN(expr1, expr2, ...) - // or - // build.BindNReturn(expr1, expr2, ...) - // or - // build.Bind(build.MergeSources(expr1, expr2), ...) - | SynExpr.LetOrUseBang(bindDebugPoint=spBind; isUse=false; isFromSource=isFromSource; pat=letPat; rhs=letRhsExpr; andBangs=andBangBindings; body=innerComp; range=letBindRange) -> - if not (cenv.g.langVersion.SupportsFeature LanguageFeature.AndBang) then - error(Error(FSComp.SR.tcAndBangNotSupported(), comp.Range)) - - if isQuery then - error(Error(FSComp.SR.tcBindMayNotBeUsedInQueries(), letBindRange)) - - let mBind = match spBind with DebugPointAtBinding.Yes m -> m | _ -> letRhsExpr.Range - let sources = (letRhsExpr :: [for SynExprAndBang(body=andExpr) in andBangBindings -> andExpr ]) |> List.map (mkSourceExprConditional isFromSource) - let pats = letPat :: [for SynExprAndBang(pat = andPat) in andBangBindings -> andPat ] - let sourcesRange = sources |> List.map (fun e -> e.Range) |> List.reduce unionRanges - - let numSources = sources.Length - let bindReturnNName = "Bind"+string numSources+"Return" - let bindNName = "Bind"+string numSources - - // Check if this is a Bind2Return etc. - let hasBindReturnN = not (isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBind ad bindReturnNName builderTy)) - if hasBindReturnN && Option.isSome (convertSimpleReturnToExpr varSpace innerComp) then - let consumePat = SynPat.Tuple(false, pats, [], letPat.Range) + let _, _, vspecs, envinner, _ = + TcMatchPattern cenv (NewInferenceType g) env tpenv consumePat None - // Add the variables to the query variable space, on demand - let varSpace = - addVarsToVarSpace varSpace (fun _mCustomOp env -> - use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType g) env tpenv consumePat None vspecs, envinner) - Some (transBind q varSpace mBind (addBindDebugPoint spBind) bindNName sources consumePat innerComp translatedCtxt) - - else + Some(transBind q varSpace mBind (addBindDebugPoint spBind) bindNName sources consumePat innerComp translatedCtxt) - // Check if this is a Bind2 etc. - let hasBindN = not (isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBind ad bindNName builderTy)) - if hasBindN then - let consumePat = SynPat.Tuple(false, pats, [], letPat.Range) + else - // Add the variables to the query variable space, on demand - let varSpace = - addVarsToVarSpace varSpace (fun _mCustomOp env -> + // Check if this is a Bind2 etc. + let hasBindN = + not ( + isNil ( + TryFindIntrinsicOrExtensionMethInfo + ResultCollectionSettings.AtMostOneResult + cenv + env + mBind + ad + bindNName + builderTy + ) + ) + + if hasBindN then + let consumePat = SynPat.Tuple(false, pats, [], letPat.Range) + + // Add the variables to the query variable space, on demand + let varSpace = + addVarsToVarSpace varSpace (fun _mCustomOp env -> use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType g) env tpenv consumePat None - vspecs, envinner) - Some (transBind q varSpace mBind (addBindDebugPoint spBind) bindNName sources consumePat innerComp translatedCtxt) - else + let _, _, vspecs, envinner, _ = + TcMatchPattern cenv (NewInferenceType g) env tpenv consumePat None - // Look for the maximum supported MergeSources, MergeSources3, ... - let mkMergeSourcesName n = if n = 2 then "MergeSources" else "MergeSources"+(string n) + vspecs, envinner) - let maxMergeSources = - let rec loop (n: int) = - let mergeSourcesName = mkMergeSourcesName n - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBind ad mergeSourcesName builderTy) then - (n-1) - else - loop (n+1) - loop 2 + Some(transBind q varSpace mBind (addBindDebugPoint spBind) bindNName sources consumePat innerComp translatedCtxt) + else - if maxMergeSources = 1 then error(Error(FSComp.SR.tcRequireMergeSourcesOrBindN(bindNName), mBind)) + // Look for the maximum supported MergeSources, MergeSources3, ... + let mkMergeSourcesName n = + if n = 2 then + "MergeSources" + else + "MergeSources" + (string n) + + let maxMergeSources = + let rec loop (n: int) = + let mergeSourcesName = mkMergeSourcesName n + + if + isNil ( + TryFindIntrinsicOrExtensionMethInfo + ResultCollectionSettings.AtMostOneResult + cenv + env + mBind + ad + mergeSourcesName + builderTy + ) + then + (n - 1) + else + loop (n + 1) + + loop 2 + + if maxMergeSources = 1 then + error (Error(FSComp.SR.tcRequireMergeSourcesOrBindN (bindNName), mBind)) + + let rec mergeSources (sourcesAndPats: (SynExpr * SynPat) list) = + let numSourcesAndPats = sourcesAndPats.Length + assert (numSourcesAndPats <> 0) + + if numSourcesAndPats = 1 then + sourcesAndPats[0] + + elif numSourcesAndPats <= maxMergeSources then + + // Call MergeSources2(e1, e2), MergeSources3(e1, e2, e3) etc + let mergeSourcesName = mkMergeSourcesName numSourcesAndPats + + if + isNil ( + TryFindIntrinsicOrExtensionMethInfo + ResultCollectionSettings.AtMostOneResult + cenv + env + mBind + ad + mergeSourcesName + builderTy + ) + then + error (Error(FSComp.SR.tcRequireMergeSourcesOrBindN (bindNName), mBind)) + + let source = mkSynCall mergeSourcesName sourcesRange (List.map fst sourcesAndPats) + let pat = SynPat.Tuple(false, List.map snd sourcesAndPats, [], letPat.Range) + source, pat - let rec mergeSources (sourcesAndPats: (SynExpr * SynPat) list) = - let numSourcesAndPats = sourcesAndPats.Length - assert (numSourcesAndPats <> 0) - if numSourcesAndPats = 1 then - sourcesAndPats[0] + else - elif numSourcesAndPats <= maxMergeSources then + // Call MergeSourcesMax(e1, e2, e3, e4, (...)) + let nowSourcesAndPats, laterSourcesAndPats = + List.splitAt (maxMergeSources - 1) sourcesAndPats - // Call MergeSources2(e1, e2), MergeSources3(e1, e2, e3) etc - let mergeSourcesName = mkMergeSourcesName numSourcesAndPats + let mergeSourcesName = mkMergeSourcesName maxMergeSources - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBind ad mergeSourcesName builderTy) then - error(Error(FSComp.SR.tcRequireMergeSourcesOrBindN(bindNName), mBind)) + if + isNil ( + TryFindIntrinsicOrExtensionMethInfo + ResultCollectionSettings.AtMostOneResult + cenv + env + mBind + ad + mergeSourcesName + builderTy + ) + then + error (Error(FSComp.SR.tcRequireMergeSourcesOrBindN (bindNName), mBind)) - let source = mkSynCall mergeSourcesName sourcesRange (List.map fst sourcesAndPats) - let pat = SynPat.Tuple(false, List.map snd sourcesAndPats, [], letPat.Range) - source, pat + let laterSource, laterPat = mergeSources laterSourcesAndPats - else + let source = + mkSynCall mergeSourcesName sourcesRange (List.map fst nowSourcesAndPats @ [ laterSource ]) - // Call MergeSourcesMax(e1, e2, e3, e4, (...)) - let nowSourcesAndPats, laterSourcesAndPats = List.splitAt (maxMergeSources - 1) sourcesAndPats - let mergeSourcesName = mkMergeSourcesName maxMergeSources + let pat = + SynPat.Tuple(false, List.map snd nowSourcesAndPats @ [ laterPat ], [], letPat.Range) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBind ad mergeSourcesName builderTy) then - error(Error(FSComp.SR.tcRequireMergeSourcesOrBindN(bindNName), mBind)) + source, pat - let laterSource, laterPat = mergeSources laterSourcesAndPats - let source = mkSynCall mergeSourcesName sourcesRange (List.map fst nowSourcesAndPats @ [laterSource]) - let pat = SynPat.Tuple(false, List.map snd nowSourcesAndPats @ [laterPat], [], letPat.Range) - source, pat + let mergedSources, consumePat = mergeSources (List.zip sources pats) - let mergedSources, consumePat = mergeSources (List.zip sources pats) - - // Add the variables to the query variable space, on demand - let varSpace = - addVarsToVarSpace varSpace (fun _mCustomOp env -> + // Add the variables to the query variable space, on demand + let varSpace = + addVarsToVarSpace varSpace (fun _mCustomOp env -> use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType g) env tpenv consumePat None - vspecs, envinner) - - // Build the 'Bind' call - Some (transBind q varSpace mBind (addBindDebugPoint spBind) "Bind" [mergedSources] consumePat innerComp translatedCtxt) - - | SynExpr.Match (spMatch, expr, clauses, m, trivia) -> - if isQuery then error(Error(FSComp.SR.tcMatchMayNotBeUsedWithQuery(), trivia.MatchKeyword)) - let clauses = clauses |> List.map (fun (SynMatchClause(pat, cond, innerComp, patm, sp, trivia)) -> SynMatchClause(pat, cond, transNoQueryOps innerComp, patm, sp, trivia)) - Some(translatedCtxt (SynExpr.Match (spMatch, expr, clauses, m, trivia))) - - // 'match! expr with pats ...' --> build.Bind(e1, (function pats ...)) - // FUTURE: consider allowing translation to BindReturn - | SynExpr.MatchBang (spMatch, expr, clauses, _m, trivia) -> - let inputExpr = mkSourceExpr expr - if isQuery then error(Error(FSComp.SR.tcMatchMayNotBeUsedWithQuery(), trivia.MatchBangKeyword)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env trivia.MatchBangKeyword ad "Bind" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("Bind"), trivia.MatchBangKeyword)) + let _, _, vspecs, envinner, _ = + TcMatchPattern cenv (NewInferenceType g) env tpenv consumePat None - let clauses = clauses |> List.map (fun (SynMatchClause(pat, cond, innerComp, patm, sp, trivia)) -> SynMatchClause(pat, cond, transNoQueryOps innerComp, patm, sp, trivia)) - let consumeExpr = SynExpr.MatchLambda (false, trivia.MatchBangKeyword, clauses, DebugPointAtBinding.NoneAtInvisible, trivia.MatchBangKeyword) + vspecs, envinner) - let callExpr = - mkSynCall "Bind" trivia.MatchBangKeyword [inputExpr; consumeExpr] - |> addBindDebugPoint spMatch - - Some(translatedCtxt callExpr) + // Build the 'Bind' call + Some( + transBind + q + varSpace + mBind + (addBindDebugPoint spBind) + "Bind" + [ mergedSources ] + consumePat + innerComp + translatedCtxt + ) + + | SynExpr.Match(spMatch, expr, clauses, m, trivia) -> + if isQuery then + error (Error(FSComp.SR.tcMatchMayNotBeUsedWithQuery (), trivia.MatchKeyword)) + + let clauses = + clauses + |> List.map (fun (SynMatchClause(pat, cond, innerComp, patm, sp, trivia)) -> + SynMatchClause(pat, cond, transNoQueryOps innerComp, patm, sp, trivia)) + + Some(translatedCtxt (SynExpr.Match(spMatch, expr, clauses, m, trivia))) + + // 'match! expr with pats ...' --> build.Bind(e1, (function pats ...)) + // FUTURE: consider allowing translation to BindReturn + | SynExpr.MatchBang(spMatch, expr, clauses, _m, trivia) -> + let inputExpr = mkSourceExpr expr + + if isQuery then + error (Error(FSComp.SR.tcMatchMayNotBeUsedWithQuery (), trivia.MatchBangKeyword)) + + if + isNil ( + TryFindIntrinsicOrExtensionMethInfo + ResultCollectionSettings.AtMostOneResult + cenv + env + trivia.MatchBangKeyword + ad + "Bind" + builderTy + ) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("Bind"), trivia.MatchBangKeyword)) + + let clauses = + clauses + |> List.map (fun (SynMatchClause(pat, cond, innerComp, patm, sp, trivia)) -> + SynMatchClause(pat, cond, transNoQueryOps innerComp, patm, sp, trivia)) + + let consumeExpr = + SynExpr.MatchLambda( + false, + trivia.MatchBangKeyword, + clauses, + DebugPointAtBinding.NoneAtInvisible, + trivia.MatchBangKeyword + ) + + let callExpr = + mkSynCall "Bind" trivia.MatchBangKeyword [ inputExpr; consumeExpr ] + |> addBindDebugPoint spMatch + + Some(translatedCtxt callExpr) + + | SynExpr.TryWith(innerComp, clauses, mTryToLast, spTry, spWith, trivia) -> + let mTry = + match spTry with + | DebugPointAtTry.Yes _ -> trivia.TryKeyword.NoteSourceConstruct(NotedSourceConstruct.Try) + | _ -> trivia.TryKeyword + + let spWith2 = + match spWith with + | DebugPointAtWith.Yes _ -> DebugPointAtBinding.Yes trivia.WithKeyword + | _ -> DebugPointAtBinding.NoneAtInvisible + + if isQuery then + error (Error(FSComp.SR.tcTryWithMayNotBeUsedInQueries (), mTry)) + + let clauses = + clauses + |> List.map (fun (SynMatchClause(pat, cond, clauseComp, patm, sp, trivia)) -> + SynMatchClause(pat, cond, transNoQueryOps clauseComp, patm, sp, trivia)) + + let consumeExpr = + SynExpr.MatchLambda(true, mTryToLast, clauses, spWith2, mTryToLast) + + if + isNil ( + TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "TryWith" builderTy + ) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("TryWith"), mTry)) + + if + isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "Delay" builderTy) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("Delay"), mTry)) + + let innerExpr = transNoQueryOps innerComp + + let innerExpr = + match spTry with + | DebugPointAtTry.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mTry, true, innerExpr) + | _ -> innerExpr + + let callExpr = + mkSynCall "TryWith" mTry [ mkSynCall "Delay" mTry [ mkSynDelay2 innerExpr ]; consumeExpr ] + + Some(translatedCtxt callExpr) + + | SynExpr.YieldOrReturnFrom((true, _), synYieldExpr, m) -> + let yieldFromExpr = mkSourceExpr synYieldExpr + + if + isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "YieldFrom" builderTy) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("YieldFrom"), m)) + + let yieldFromCall = mkSynCall "YieldFrom" m [ yieldFromExpr ] + + let yieldFromCall = + if IsControlFlowExpression synYieldExpr then + yieldFromCall + else + SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes m, false, yieldFromCall) - | SynExpr.TryWith (innerComp, clauses, mTryToLast, spTry, spWith, trivia) -> - let mTry = match spTry with DebugPointAtTry.Yes _ -> trivia.TryKeyword.NoteSourceConstruct(NotedSourceConstruct.Try) | _ -> trivia.TryKeyword - let spWith2 = match spWith with DebugPointAtWith.Yes _ -> DebugPointAtBinding.Yes trivia.WithKeyword | _ -> DebugPointAtBinding.NoneAtInvisible - - if isQuery then error(Error(FSComp.SR.tcTryWithMayNotBeUsedInQueries(), mTry)) + Some(translatedCtxt yieldFromCall) - let clauses = clauses |> List.map (fun (SynMatchClause(pat, cond, clauseComp, patm, sp, trivia)) -> SynMatchClause(pat, cond, transNoQueryOps clauseComp, patm, sp, trivia)) - let consumeExpr = SynExpr.MatchLambda(true, mTryToLast, clauses, spWith2, mTryToLast) + | SynExpr.YieldOrReturnFrom((false, _), synReturnExpr, m) -> + let returnFromExpr = mkSourceExpr synReturnExpr - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "TryWith" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("TryWith"), mTry)) + if isQuery then + error (Error(FSComp.SR.tcReturnMayNotBeUsedInQueries (), m)) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "Delay" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mTry)) + if + isNil ( + TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "ReturnFrom" builderTy + ) + then + error (Error(FSComp.SR.tcRequireBuilderMethod ("ReturnFrom"), m)) - let innerExpr = transNoQueryOps innerComp + let returnFromCall = mkSynCall "ReturnFrom" m [ returnFromExpr ] - let innerExpr = - match spTry with - | DebugPointAtTry.Yes _ -> - SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mTry, true, innerExpr) - | _ -> innerExpr - - let callExpr = - mkSynCall "TryWith" mTry [ - mkSynCall "Delay" mTry [mkSynDelay2 innerExpr] - consumeExpr - ] - - Some(translatedCtxt callExpr) - - | SynExpr.YieldOrReturnFrom ((true, _), synYieldExpr, m) -> - let yieldFromExpr = mkSourceExpr synYieldExpr - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "YieldFrom" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("YieldFrom"), m)) - - let yieldFromCall = mkSynCall "YieldFrom" m [yieldFromExpr] - - let yieldFromCall = - if IsControlFlowExpression synYieldExpr then - yieldFromCall - else - SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes m, false, yieldFromCall) - - Some (translatedCtxt yieldFromCall) - - | SynExpr.YieldOrReturnFrom ((false, _), synReturnExpr, m) -> - let returnFromExpr = mkSourceExpr synReturnExpr - if isQuery then error(Error(FSComp.SR.tcReturnMayNotBeUsedInQueries(), m)) + let returnFromCall = + if IsControlFlowExpression synReturnExpr then + returnFromCall + else + SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes m, false, returnFromCall) - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "ReturnFrom" builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod("ReturnFrom"), m)) + Some(translatedCtxt returnFromCall) - let returnFromCall = mkSynCall "ReturnFrom" m [returnFromExpr] + | SynExpr.YieldOrReturn((isYield, _), synYieldOrReturnExpr, m) -> + let methName = (if isYield then "Yield" else "Return") - let returnFromCall = - if IsControlFlowExpression synReturnExpr then - returnFromCall - else - SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes m, false, returnFromCall) + if isQuery && not isYield then + error (Error(FSComp.SR.tcReturnMayNotBeUsedInQueries (), m)) - Some (translatedCtxt returnFromCall) + if + isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad methName builderTy) + then + error (Error(FSComp.SR.tcRequireBuilderMethod (methName), m)) - | SynExpr.YieldOrReturn ((isYield, _), synYieldOrReturnExpr, m) -> - let methName = (if isYield then "Yield" else "Return") - if isQuery && not isYield then error(Error(FSComp.SR.tcReturnMayNotBeUsedInQueries(), m)) + let yieldOrReturnCall = mkSynCall methName m [ synYieldOrReturnExpr ] - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad methName builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod(methName), m)) - - let yieldOrReturnCall = mkSynCall methName m [synYieldOrReturnExpr] - - let yieldOrReturnCall = - if IsControlFlowExpression synYieldOrReturnExpr then - yieldOrReturnCall - else - SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes m, false, yieldOrReturnCall) + let yieldOrReturnCall = + if IsControlFlowExpression synYieldOrReturnExpr then + yieldOrReturnCall + else + SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes m, false, yieldOrReturnCall) - Some(translatedCtxt yieldOrReturnCall) + Some(translatedCtxt yieldOrReturnCall) - | _ -> None + | _ -> None and consumeCustomOpClauses q (varSpace: LazyWithContext<_, _>) dataCompPrior compClausesExpr lastUsesBind mClause = @@ -1525,10 +2406,10 @@ let TcComputationExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (mWhol let varSpaceSimplePat = mkSimplePatForVarSpace mClause patvs let varSpacePat = mkPatForVarSpace mClause patvs - match compClausesExpr with - + match compClausesExpr with + // Detect one custom operation... This clause will always match at least once... - | OptionalSequential (CustomOperationClause (nm, opDatas, opExpr, mClause, optionalIntoPat), optionalCont) -> + | OptionalSequential(CustomOperationClause(nm, opDatas, opExpr, mClause, optionalIntoPat), optionalCont) -> let opName, _, _, _, _, _, _, _, methInfo = opDatas[0] let isLikeZip = customOperationIsLikeZip nm @@ -1536,16 +2417,18 @@ let TcComputationExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (mWhol let isLikeGroupJoin = customOperationIsLikeZip nm // Record the resolution of the custom operation for posterity - let item = Item.CustomOperation (opName, (fun () -> customOpUsageText nm), Some methInfo) + let item = + Item.CustomOperation(opName, (fun () -> customOpUsageText nm), Some methInfo) // FUTURE: consider whether we can do better than emptyTyparInst here, in order to display instantiations // of type variables in the quick info provided in the IDE. CallNameResolutionSink cenv.tcSink (nm.idRange, env.NameEnv, item, emptyTyparInst, ItemOccurence.Use, env.eAccessRights) if isLikeZip || isLikeJoin || isLikeGroupJoin then - errorR(Error(FSComp.SR.tcBinaryOperatorRequiresBody(nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) - match optionalCont with - | None -> + errorR (Error(FSComp.SR.tcBinaryOperatorRequiresBody (nm.idText, Option.get (customOpUsageText nm)), nm.idRange)) + + match optionalCont with + | None -> // we are about to drop the 'opExpr' AST on the floor. we've already reported an error. attempt to get name resolutions before dropping it RecordNameAndTypeResolutions cenv env tpenv opExpr dataCompPrior @@ -1557,217 +2440,346 @@ let TcComputationExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (mWhol let expectedArgCount = tryExpectedArgCountForCustomOperator nm - let dataCompAfterOp = - match opExpr with + let dataCompAfterOp = + match opExpr with | StripApps(SingleIdent nm, args) -> let argCountsMatch = match expectedArgCount with | Some n -> n = args.Length | None -> cenv.g.langVersion.SupportsFeature LanguageFeature.OverloadsForCustomOperations + if argCountsMatch then // Check for the [] attribute on each argument position - let args = args |> List.mapi (fun i arg -> - if isCustomOperationProjectionParameter (i+1) nm then - SynExpr.Lambda (false, false, varSpaceSimplePat, arg, None, arg.Range.MakeSynthetic(), SynExprLambdaTrivia.Zero) - else arg) + let args = + args + |> List.mapi (fun i arg -> + if isCustomOperationProjectionParameter (i + 1) nm then + SynExpr.Lambda( + false, + false, + varSpaceSimplePat, + arg, + None, + arg.Range.MakeSynthetic(), + SynExprLambdaTrivia.Zero + ) + else + arg) + mkSynCall methInfo.DisplayName mClause (dataCompPrior :: args) - else + else let expectedArgCount = defaultArg expectedArgCount 0 - errorR(Error(FSComp.SR.tcCustomOperationHasIncorrectArgCount(nm.idText, expectedArgCount, args.Length), nm.idRange)) - mkSynCall methInfo.DisplayName mClause ([ dataCompPrior ] @ List.init expectedArgCount (fun i -> arbExpr("_arg" + string i, mClause))) + + errorR ( + Error( + FSComp.SR.tcCustomOperationHasIncorrectArgCount (nm.idText, expectedArgCount, args.Length), + nm.idRange + ) + ) + + mkSynCall + methInfo.DisplayName + mClause + ([ dataCompPrior ] + @ List.init expectedArgCount (fun i -> arbExpr ("_arg" + string i, mClause))) | _ -> failwith "unreachable" - match optionalCont with - | None -> - match optionalIntoPat with - | Some intoPat -> errorR(Error(FSComp.SR.tcIntoNeedsRestOfQuery(), intoPat.Range)) + match optionalCont with + | None -> + match optionalIntoPat with + | Some intoPat -> errorR (Error(FSComp.SR.tcIntoNeedsRestOfQuery (), intoPat.Range)) | None -> () + dataCompAfterOp - | Some contExpr -> - - // select a.Name into name; ... - // distinct into d; ... - // - // Rebind the into pattern and process the rest of the clauses - match optionalIntoPat with - | Some intoPat -> - if not (customOperationAllowsInto nm) then - error(Error(FSComp.SR.tcOperatorDoesntAcceptInto(nm.idText), intoPat.Range)) - - // Rebind using either for ... or let!.... - let rebind = - if maintainsVarSpaceUsingBind then - SynExpr.LetOrUseBang (DebugPointAtBinding.NoneAtLet, false, false, intoPat, dataCompAfterOp, [], contExpr, intoPat.Range, SynExprLetOrUseBangTrivia.Zero) - else - SynExpr.ForEach (DebugPointAtFor.No, DebugPointAtInOrTo.No, SeqExprOnly false, false, intoPat, dataCompAfterOp, contExpr, intoPat.Range) - - trans CompExprTranslationPass.Initial q emptyVarSpace rebind id - - // select a.Name; ... - // distinct; ... - // - // Process the rest of the clauses - | None -> - if maintainsVarSpace || maintainsVarSpaceUsingBind then - consumeCustomOpClauses q varSpace dataCompAfterOp contExpr maintainsVarSpaceUsingBind mClause + | Some contExpr -> + + // select a.Name into name; ... + // distinct into d; ... + // + // Rebind the into pattern and process the rest of the clauses + match optionalIntoPat with + | Some intoPat -> + if not (customOperationAllowsInto nm) then + error (Error(FSComp.SR.tcOperatorDoesntAcceptInto (nm.idText), intoPat.Range)) + + // Rebind using either for ... or let!.... + let rebind = + if maintainsVarSpaceUsingBind then + SynExpr.LetOrUseBang( + DebugPointAtBinding.NoneAtLet, + false, + false, + intoPat, + dataCompAfterOp, + [], + contExpr, + intoPat.Range, + SynExprLetOrUseBangTrivia.Zero + ) else - consumeCustomOpClauses q emptyVarSpace dataCompAfterOp contExpr false mClause + SynExpr.ForEach( + DebugPointAtFor.No, + DebugPointAtInOrTo.No, + SeqExprOnly false, + false, + intoPat, + dataCompAfterOp, + contExpr, + intoPat.Range + ) + + trans CompExprTranslationPass.Initial q emptyVarSpace rebind id + + // select a.Name; ... + // distinct; ... + // + // Process the rest of the clauses + | None -> + if maintainsVarSpace || maintainsVarSpaceUsingBind then + consumeCustomOpClauses q varSpace dataCompAfterOp contExpr maintainsVarSpaceUsingBind mClause + else + consumeCustomOpClauses q emptyVarSpace dataCompAfterOp contExpr false mClause - // No more custom operator clauses in compClausesExpr, but there may be clauses like join, yield etc. + // No more custom operator clauses in compClausesExpr, but there may be clauses like join, yield etc. // Bind/iterate the dataCompPrior and use compClausesExpr as the body. - | _ -> + | _ -> // Rebind using either for ... or let!.... - let rebind = - if lastUsesBind then - SynExpr.LetOrUseBang (DebugPointAtBinding.NoneAtLet, false, false, varSpacePat, dataCompPrior, [], compClausesExpr, compClausesExpr.Range, SynExprLetOrUseBangTrivia.Zero) - else - SynExpr.ForEach (DebugPointAtFor.No, DebugPointAtInOrTo.No, SeqExprOnly false, false, varSpacePat, dataCompPrior, compClausesExpr, compClausesExpr.Range) - + let rebind = + if lastUsesBind then + SynExpr.LetOrUseBang( + DebugPointAtBinding.NoneAtLet, + false, + false, + varSpacePat, + dataCompPrior, + [], + compClausesExpr, + compClausesExpr.Range, + SynExprLetOrUseBangTrivia.Zero + ) + else + SynExpr.ForEach( + DebugPointAtFor.No, + DebugPointAtInOrTo.No, + SeqExprOnly false, + false, + varSpacePat, + dataCompPrior, + compClausesExpr, + compClausesExpr.Range + ) + trans CompExprTranslationPass.Initial q varSpace rebind id and transNoQueryOps comp = trans CompExprTranslationPass.Initial CustomOperationsMode.Denied emptyVarSpace comp id - and trans firstTry q varSpace comp translatedCtxt = - match tryTrans firstTry q varSpace comp translatedCtxt with + and trans firstTry q varSpace comp translatedCtxt = + match tryTrans firstTry q varSpace comp translatedCtxt with | Some e -> e - | None -> + | None -> // This only occurs in final position in a sequence - match comp with + match comp with // "do! expr;" in final position is treated as { let! () = expr in return () } when Return is provided (and no Zero with Default attribute is available) or as { let! () = expr in zero } otherwise - | SynExpr.DoBang (rhsExpr, m) -> + | SynExpr.DoBang(rhsExpr, m) -> let mUnit = rhsExpr.Range let rhsExpr = mkSourceExpr rhsExpr - if isQuery then error(Error(FSComp.SR.tcBindMayNotBeUsedInQueries(), m)) + + if isQuery then + error (Error(FSComp.SR.tcBindMayNotBeUsedInQueries (), m)) + let bodyExpr = - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Return" builderTy) then + if + isNil ( + TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Return" builderTy + ) + then SynExpr.ImplicitZero m else - match TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Zero" builderTy with + match + TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Zero" builderTy + with | minfo :: _ when MethInfoHasAttribute cenv.g m cenv.g.attrib_DefaultValueAttribute minfo -> SynExpr.ImplicitZero m - | _ -> SynExpr.YieldOrReturn ((false, true), SynExpr.Const (SynConst.Unit, m), m) - let letBangBind = SynExpr.LetOrUseBang (DebugPointAtBinding.NoneAtDo, false, false, SynPat.Const(SynConst.Unit, mUnit), rhsExpr, [], bodyExpr, m, SynExprLetOrUseBangTrivia.Zero) + | _ -> SynExpr.YieldOrReturn((false, true), SynExpr.Const(SynConst.Unit, m), m) + + let letBangBind = + SynExpr.LetOrUseBang( + DebugPointAtBinding.NoneAtDo, + false, + false, + SynPat.Const(SynConst.Unit, mUnit), + rhsExpr, + [], + bodyExpr, + m, + SynExprLetOrUseBangTrivia.Zero + ) + trans CompExprTranslationPass.Initial q varSpace letBangBind translatedCtxt // "expr;" in final position is treated as { expr; zero } // Suppress the sequence point on the "zero" - | _ -> + | _ -> // Check for 'where x > y' and other mis-applications of infix operators. If detected, give a good error message, and just ignore comp - if isQuery && checkForBinaryApp comp then + if isQuery && checkForBinaryApp comp then trans CompExprTranslationPass.Initial q varSpace (SynExpr.ImplicitZero comp.Range) translatedCtxt else - if isQuery && not comp.IsArbExprAndThusAlreadyReportedError then - match comp with + if isQuery && not comp.IsArbExprAndThusAlreadyReportedError then + match comp with | SynExpr.JoinIn _ -> () // an error will be reported later when we process innerComp1 as a sequential - | _ -> errorR(Error(FSComp.SR.tcUnrecognizedQueryOperator(), comp.RangeOfFirstPortion)) + | _ -> errorR (Error(FSComp.SR.tcUnrecognizedQueryOperator (), comp.RangeOfFirstPortion)) + trans CompExprTranslationPass.Initial q varSpace (SynExpr.ImplicitZero comp.Range) (fun holeFill -> - let fillExpr = - if enableImplicitYield then - let implicitYieldExpr = mkSynCall "Yield" comp.Range [comp] - SynExpr.SequentialOrImplicitYield(DebugPointAtSequential.SuppressExpr, comp, holeFill, implicitYieldExpr, comp.Range) + let fillExpr = + if enableImplicitYield then + let implicitYieldExpr = mkSynCall "Yield" comp.Range [ comp ] + + SynExpr.SequentialOrImplicitYield( + DebugPointAtSequential.SuppressExpr, + comp, + holeFill, + implicitYieldExpr, + comp.Range + ) else SynExpr.Sequential(DebugPointAtSequential.SuppressExpr, true, comp, holeFill, comp.Range) - translatedCtxt fillExpr) - and transBind q varSpace bindRange addBindDebugPoint bindName bindArgs (consumePat: SynPat) (innerComp: SynExpr) translatedCtxt = + translatedCtxt fillExpr) + + and transBind q varSpace bindRange addBindDebugPoint bindName bindArgs (consumePat: SynPat) (innerComp: SynExpr) translatedCtxt = let innerRange = innerComp.Range - - let innerCompReturn = + + let innerCompReturn = if cenv.g.langVersion.SupportsFeature LanguageFeature.AndBang then convertSimpleReturnToExpr varSpace innerComp - else None + else + None - match innerCompReturn with - | Some (innerExpr, customOpInfo) when - (let bindName = bindName + "Return" - not (isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad bindName builderTy))) -> + match innerCompReturn with + | Some(innerExpr, customOpInfo) when + (let bindName = bindName + "Return" + + not ( + isNil ( + TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad bindName builderTy + ) + )) + -> let bindName = bindName + "Return" - + // Build the `BindReturn` call let dataCompPriorToOp = - let consumeExpr = SynExpr.MatchLambda(false, consumePat.Range, [SynMatchClause(consumePat, None, innerExpr, innerRange, DebugPointAtTarget.Yes, SynMatchClauseTrivia.Zero)], DebugPointAtBinding.NoneAtInvisible, innerRange) - translatedCtxt (mkSynCall bindName bindRange (bindArgs @ [consumeExpr])) - - match customOpInfo with + let consumeExpr = + SynExpr.MatchLambda( + false, + consumePat.Range, + [ + SynMatchClause(consumePat, None, innerExpr, innerRange, DebugPointAtTarget.Yes, SynMatchClauseTrivia.Zero) + ], + DebugPointAtBinding.NoneAtInvisible, + innerRange + ) + + translatedCtxt (mkSynCall bindName bindRange (bindArgs @ [ consumeExpr ])) + + match customOpInfo with | None -> dataCompPriorToOp - | Some (innerComp, mClause) -> + | Some(innerComp, mClause) -> // If the `BindReturn` was forced by a custom operation, continue to process the clauses of the CustomOp consumeCustomOpClauses q varSpace dataCompPriorToOp innerComp false mClause - | _ -> + | _ -> - if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad bindName builderTy) then - error(Error(FSComp.SR.tcRequireBuilderMethod(bindName), bindRange)) + if + isNil ( + TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env bindRange ad bindName builderTy + ) + then + error (Error(FSComp.SR.tcRequireBuilderMethod (bindName), bindRange)) // Build the `Bind` call trans CompExprTranslationPass.Initial q varSpace innerComp (fun holeFill -> - let consumeExpr = SynExpr.MatchLambda(false, consumePat.Range, [SynMatchClause(consumePat, None, holeFill, innerRange, DebugPointAtTarget.Yes, SynMatchClauseTrivia.Zero)], DebugPointAtBinding.NoneAtInvisible, innerRange) - let bindCall = mkSynCall bindName bindRange (bindArgs @ [consumeExpr]) + let consumeExpr = + SynExpr.MatchLambda( + false, + consumePat.Range, + [ + SynMatchClause(consumePat, None, holeFill, innerRange, DebugPointAtTarget.Yes, SynMatchClauseTrivia.Zero) + ], + DebugPointAtBinding.NoneAtInvisible, + innerRange + ) + + let bindCall = mkSynCall bindName bindRange (bindArgs @ [ consumeExpr ]) translatedCtxt (bindCall |> addBindDebugPoint)) /// This function is for desugaring into .Bind{N}Return calls if possible /// The outer option indicates if .BindReturn is possible. When it returns None, .BindReturn cannot be used /// The inner option indicates if a custom operation is involved inside and convertSimpleReturnToExpr varSpace innerComp = - match innerComp with - | SynExpr.YieldOrReturn ((false, _), returnExpr, m) -> + match innerComp with + | SynExpr.YieldOrReturn((false, _), returnExpr, m) -> let returnExpr = SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes m, false, returnExpr) - Some (returnExpr, None) + Some(returnExpr, None) - | SynExpr.Match (spMatch, expr, clauses, m, trivia) -> - let clauses = - clauses |> List.map (fun (SynMatchClause(pat, cond, innerComp2, patm, sp, trivia)) -> + | SynExpr.Match(spMatch, expr, clauses, m, trivia) -> + let clauses = + clauses + |> List.map (fun (SynMatchClause(pat, cond, innerComp2, patm, sp, trivia)) -> match convertSimpleReturnToExpr varSpace innerComp2 with | None -> None // failure - | Some (_, Some _) -> None // custom op on branch = failure - | Some (innerExpr2, None) -> Some (SynMatchClause(pat, cond, innerExpr2, patm, sp, trivia))) + | Some(_, Some _) -> None // custom op on branch = failure + | Some(innerExpr2, None) -> Some(SynMatchClause(pat, cond, innerExpr2, patm, sp, trivia))) + if clauses |> List.forall Option.isSome then - Some (SynExpr.Match (spMatch, expr, (clauses |> List.map Option.get), m, trivia), None) + Some(SynExpr.Match(spMatch, expr, (clauses |> List.map Option.get), m, trivia), None) else None - | SynExpr.IfThenElse (guardExpr, thenComp, elseCompOpt, spIfToThen, isRecovery, mIfToEndOfElseBranch, trivia) -> + | SynExpr.IfThenElse(guardExpr, thenComp, elseCompOpt, spIfToThen, isRecovery, mIfToEndOfElseBranch, trivia) -> match convertSimpleReturnToExpr varSpace thenComp with | None -> None - | Some (_, Some _) -> None - | Some (thenExpr, None) -> - let elseExprOptOpt = - match elseCompOpt with - // When we are missing an 'else' part alltogether in case of 'if cond then return exp', we fallback from BindReturn into regular Bind+Return - | None -> None - | Some elseComp -> - match convertSimpleReturnToExpr varSpace elseComp with - | None -> None // failure - | Some (_, Some _) -> None // custom op on branch = failure - | Some (elseExpr, None) -> Some (Some elseExpr) - match elseExprOptOpt with - | None -> None - | Some elseExprOpt -> Some (SynExpr.IfThenElse (guardExpr, thenExpr, elseExprOpt, spIfToThen, isRecovery, mIfToEndOfElseBranch, trivia), None) + | Some(_, Some _) -> None + | Some(thenExpr, None) -> + let elseExprOptOpt = + match elseCompOpt with + // When we are missing an 'else' part alltogether in case of 'if cond then return exp', we fallback from BindReturn into regular Bind+Return + | None -> None + | Some elseComp -> + match convertSimpleReturnToExpr varSpace elseComp with + | None -> None // failure + | Some(_, Some _) -> None // custom op on branch = failure + | Some(elseExpr, None) -> Some(Some elseExpr) + + match elseExprOptOpt with + | None -> None + | Some elseExprOpt -> + Some(SynExpr.IfThenElse(guardExpr, thenExpr, elseExprOpt, spIfToThen, isRecovery, mIfToEndOfElseBranch, trivia), None) - | SynExpr.LetOrUse (isRec, false, binds, innerComp, m, trivia) -> + | SynExpr.LetOrUse(isRec, false, binds, innerComp, m, trivia) -> match convertSimpleReturnToExpr varSpace innerComp with | None -> None - | Some (_, Some _) -> None - | Some (innerExpr, None) -> Some (SynExpr.LetOrUse (isRec, false, binds, innerExpr, m, trivia), None) + | Some(_, Some _) -> None + | Some(innerExpr, None) -> Some(SynExpr.LetOrUse(isRec, false, binds, innerExpr, m, trivia), None) - | OptionalSequential (CustomOperationClause (nm, _, _, mClause, _), _) when customOperationMaintainsVarSpaceUsingBind nm -> + | OptionalSequential(CustomOperationClause(nm, _, _, mClause, _), _) when customOperationMaintainsVarSpaceUsingBind nm -> let patvs, _env = varSpace.Force comp.Range let varSpaceExpr = mkExprForVarSpace mClause patvs - - Some (varSpaceExpr, Some (innerComp, mClause)) - | SynExpr.Sequential (sp, true, innerComp1, innerComp2, m) -> + Some(varSpaceExpr, Some(innerComp, mClause)) + + | SynExpr.Sequential(sp, true, innerComp1, innerComp2, m) -> // Check the first part isn't a computation expression construct if isSimpleExpr innerComp1 then // Check the second part is a simple return match convertSimpleReturnToExpr varSpace innerComp2 with | None -> None - | Some (innerExpr2, optionalCont) -> Some (SynExpr.Sequential (sp, true, innerComp1, innerExpr2, m), optionalCont) + | Some(innerExpr2, optionalCont) -> Some(SynExpr.Sequential(sp, true, innerComp1, innerExpr2, m), optionalCont) else None @@ -1776,7 +2788,7 @@ let TcComputationExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (mWhol /// Check if an expression has no computation expression constructs and isSimpleExpr comp = - match comp with + match comp with | ForEachThenJoinOrGroupJoinOrZipClause false _ -> false | SynExpr.ForEach _ -> false | SynExpr.For _ -> false @@ -1784,61 +2796,85 @@ let TcComputationExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (mWhol | SynExpr.WhileBang _ -> false | SynExpr.TryFinally _ -> false | SynExpr.ImplicitZero _ -> false - | OptionalSequential (JoinOrGroupJoinOrZipClause _, _) -> false - | OptionalSequential (CustomOperationClause _, _) -> false - | SynExpr.Sequential (_, _, innerComp1, innerComp2, _) -> isSimpleExpr innerComp1 && isSimpleExpr innerComp2 - | SynExpr.IfThenElse (thenExpr=thenComp; elseExpr=elseCompOpt) -> - isSimpleExpr thenComp && (match elseCompOpt with None -> true | Some c -> isSimpleExpr c) - | SynExpr.LetOrUse (body=innerComp) -> isSimpleExpr innerComp + | OptionalSequential(JoinOrGroupJoinOrZipClause _, _) -> false + | OptionalSequential(CustomOperationClause _, _) -> false + | SynExpr.Sequential(_, _, innerComp1, innerComp2, _) -> isSimpleExpr innerComp1 && isSimpleExpr innerComp2 + | SynExpr.IfThenElse(thenExpr = thenComp; elseExpr = elseCompOpt) -> + isSimpleExpr thenComp + && (match elseCompOpt with + | None -> true + | Some c -> isSimpleExpr c) + | SynExpr.LetOrUse(body = innerComp) -> isSimpleExpr innerComp | SynExpr.LetOrUseBang _ -> false - | SynExpr.Match (clauses=clauses) -> - clauses |> List.forall (fun (SynMatchClause(resultExpr = innerComp)) -> isSimpleExpr innerComp) + | SynExpr.Match(clauses = clauses) -> + clauses + |> List.forall (fun (SynMatchClause(resultExpr = innerComp)) -> isSimpleExpr innerComp) | SynExpr.MatchBang _ -> false - | SynExpr.TryWith (tryExpr=innerComp; withCases=clauses) -> - isSimpleExpr innerComp && - clauses |> List.forall (fun (SynMatchClause(resultExpr = clauseComp)) -> isSimpleExpr clauseComp) + | SynExpr.TryWith(tryExpr = innerComp; withCases = clauses) -> + isSimpleExpr innerComp + && clauses + |> List.forall (fun (SynMatchClause(resultExpr = clauseComp)) -> isSimpleExpr clauseComp) | SynExpr.YieldOrReturnFrom _ -> false | SynExpr.YieldOrReturn _ -> false | SynExpr.DoBang _ -> false | _ -> true - let basicSynExpr = - trans CompExprTranslationPass.Initial (hasCustomOperations ()) (LazyWithContext.NotLazy ([], env)) comp id + let basicSynExpr = + trans CompExprTranslationPass.Initial (hasCustomOperations ()) (LazyWithContext.NotLazy([], env)) comp id - let mDelayOrQuoteOrRun = mBuilderVal.NoteSourceConstruct(NotedSourceConstruct.DelayOrQuoteOrRun).MakeSynthetic() + let mDelayOrQuoteOrRun = + mBuilderVal + .NoteSourceConstruct(NotedSourceConstruct.DelayOrQuoteOrRun) + .MakeSynthetic() // Add a call to 'Delay' if the method is present - let delayedExpr = - match TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBuilderVal ad "Delay" builderTy with + let delayedExpr = + match TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBuilderVal ad "Delay" builderTy with | [] -> basicSynExpr - | _ -> - mkSynCall "Delay" mDelayOrQuoteOrRun [(mkSynDelay2 basicSynExpr)] + | _ -> mkSynCall "Delay" mDelayOrQuoteOrRun [ (mkSynDelay2 basicSynExpr) ] // Add a call to 'Quote' if the method is present - let quotedSynExpr = - if isAutoQuote then - SynExpr.Quote (mkSynIdGet mDelayOrQuoteOrRun (CompileOpName "<@ @>"), false, delayedExpr, true, mWhole) - else delayedExpr - + let quotedSynExpr = + if isAutoQuote then + SynExpr.Quote(mkSynIdGet mDelayOrQuoteOrRun (CompileOpName "<@ @>"), false, delayedExpr, true, mWhole) + else + delayedExpr + // Add a call to 'Run' if the method is present - let runExpr = - match TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBuilderVal ad "Run" builderTy with + let runExpr = + match TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBuilderVal ad "Run" builderTy with | [] -> quotedSynExpr - | _ -> mkSynCall "Run" mDelayOrQuoteOrRun [quotedSynExpr] - - let lambdaExpr = - SynExpr.Lambda (false, false, SynSimplePats.SimplePats ([mkSynSimplePatVar false (mkSynId mBuilderVal builderValName)], [], mBuilderVal), runExpr, None, mBuilderVal, SynExprLambdaTrivia.Zero) + | _ -> mkSynCall "Run" mDelayOrQuoteOrRun [ quotedSynExpr ] + + let lambdaExpr = + SynExpr.Lambda( + false, + false, + SynSimplePats.SimplePats([ mkSynSimplePatVar false (mkSynId mBuilderVal builderValName) ], [], mBuilderVal), + runExpr, + None, + mBuilderVal, + SynExprLambdaTrivia.Zero + ) let env = match comp with - | SynExpr.YieldOrReturn ((true, _), _, _) -> { env with eContextInfo = ContextInfo.YieldInComputationExpression } - | SynExpr.YieldOrReturn ((_, true), _, _) -> { env with eContextInfo = ContextInfo.ReturnInComputationExpression } + | SynExpr.YieldOrReturn(flags = (true, _)) -> + { env with + eContextInfo = ContextInfo.YieldInComputationExpression + } + | SynExpr.YieldOrReturn(flags = (_, true)) -> + { env with + eContextInfo = ContextInfo.ReturnInComputationExpression + } | _ -> env - let lambdaExpr, tpenv = TcExpr cenv (MustEqual (mkFunTy g builderTy overallTy)) env tpenv lambdaExpr + let lambdaExpr, tpenv = + TcExpr cenv (MustEqual(mkFunTy g builderTy overallTy)) env tpenv lambdaExpr // beta-var-reduce to bind the builder using a 'let' binding - let coreExpr = mkApps cenv.g ((lambdaExpr, tyOfExpr cenv.g lambdaExpr), [], [interpExpr], mBuilderVal) + let coreExpr = + mkApps cenv.g ((lambdaExpr, tyOfExpr cenv.g lambdaExpr), [], [ interpExpr ], mBuilderVal) coreExpr, tpenv @@ -1847,13 +2883,16 @@ let mkSeqEmpty (cenv: cenv) env m genTy = let g = cenv.g let genResultTy = NewInferenceType g UnifyTypes cenv env m genTy (mkSeqTy g genResultTy) - mkCallSeqEmpty g m genResultTy + mkCallSeqEmpty g m genResultTy let mkSeqCollect (cenv: cenv) env m enumElemTy genTy lam enumExpr = let g = cenv.g let genResultTy = NewInferenceType g UnifyTypes cenv env m genTy (mkSeqTy cenv.g genResultTy) - let enumExpr = mkCoerceIfNeeded cenv.g (mkSeqTy cenv.g enumElemTy) (tyOfExpr cenv.g enumExpr) enumExpr + + let enumExpr = + mkCoerceIfNeeded cenv.g (mkSeqTy cenv.g enumElemTy) (tyOfExpr cenv.g enumExpr) enumExpr + mkCallSeqCollect cenv.g m enumElemTy genResultTy lam enumExpr let mkSeqUsing (cenv: cenv) (env: TcEnv) m resourceTy genTy resourceExpr lam = @@ -1861,58 +2900,83 @@ let mkSeqUsing (cenv: cenv) (env: TcEnv) m resourceTy genTy resourceExpr lam = AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace cenv.g.system_IDisposable_ty resourceTy let genResultTy = NewInferenceType g UnifyTypes cenv env m genTy (mkSeqTy cenv.g genResultTy) - mkCallSeqUsing cenv.g m resourceTy genResultTy resourceExpr lam + mkCallSeqUsing cenv.g m resourceTy genResultTy resourceExpr lam let mkSeqDelay (cenv: cenv) env m genTy lam = let g = cenv.g let genResultTy = NewInferenceType g UnifyTypes cenv env m genTy (mkSeqTy cenv.g genResultTy) - mkCallSeqDelay cenv.g m genResultTy (mkUnitDelayLambda cenv.g m lam) + mkCallSeqDelay cenv.g m genResultTy (mkUnitDelayLambda cenv.g m lam) let mkSeqAppend (cenv: cenv) env m genTy e1 e2 = let g = cenv.g let genResultTy = NewInferenceType g UnifyTypes cenv env m genTy (mkSeqTy cenv.g genResultTy) - let e1 = mkCoerceIfNeeded cenv.g (mkSeqTy cenv.g genResultTy) (tyOfExpr cenv.g e1) e1 - let e2 = mkCoerceIfNeeded cenv.g (mkSeqTy cenv.g genResultTy) (tyOfExpr cenv.g e2) e2 - mkCallSeqAppend cenv.g m genResultTy e1 e2 + + let e1 = + mkCoerceIfNeeded cenv.g (mkSeqTy cenv.g genResultTy) (tyOfExpr cenv.g e1) e1 + + let e2 = + mkCoerceIfNeeded cenv.g (mkSeqTy cenv.g genResultTy) (tyOfExpr cenv.g e2) e2 + + mkCallSeqAppend cenv.g m genResultTy e1 e2 let mkSeqFromFunctions (cenv: cenv) env m genTy e1 e2 = let g = cenv.g let genResultTy = NewInferenceType g UnifyTypes cenv env m genTy (mkSeqTy cenv.g genResultTy) - let e2 = mkCoerceIfNeeded cenv.g (mkSeqTy cenv.g genResultTy) (tyOfExpr cenv.g e2) e2 - mkCallSeqGenerated cenv.g m genResultTy e1 e2 + + let e2 = + mkCoerceIfNeeded cenv.g (mkSeqTy cenv.g genResultTy) (tyOfExpr cenv.g e2) e2 + + mkCallSeqGenerated cenv.g m genResultTy e1 e2 let mkSeqFinally (cenv: cenv) env m genTy e1 e2 = let g = cenv.g let genResultTy = NewInferenceType g UnifyTypes cenv env m genTy (mkSeqTy cenv.g genResultTy) - let e1 = mkCoerceIfNeeded cenv.g (mkSeqTy cenv.g genResultTy) (tyOfExpr cenv.g e1) e1 - mkCallSeqFinally cenv.g m genResultTy e1 e2 + + let e1 = + mkCoerceIfNeeded cenv.g (mkSeqTy cenv.g genResultTy) (tyOfExpr cenv.g e1) e1 + + mkCallSeqFinally cenv.g m genResultTy e1 e2 let mkSeqTryWith (cenv: cenv) env m genTy origSeq exnFilter exnHandler = let g = cenv.g let genResultTy = NewInferenceType g UnifyTypes cenv env m genTy (mkSeqTy cenv.g genResultTy) - let origSeq = mkCoerceIfNeeded cenv.g (mkSeqTy cenv.g genResultTy) (tyOfExpr cenv.g origSeq) origSeq - mkCallSeqTryWith cenv.g m genResultTy origSeq exnFilter exnHandler -let mkSeqExprMatchClauses (pat, vspecs) innerExpr = - [MatchClause(pat, None, TTarget(vspecs, innerExpr, None), pat.Range) ] + let origSeq = + mkCoerceIfNeeded cenv.g (mkSeqTy cenv.g genResultTy) (tyOfExpr cenv.g origSeq) origSeq + + mkCallSeqTryWith cenv.g m genResultTy origSeq exnFilter exnHandler -let compileSeqExprMatchClauses (cenv: cenv) env inputExprMark (pat: Pattern, vspecs) innerExpr inputExprOpt bindPatTy genInnerTy = +let mkSeqExprMatchClauses (pat, vspecs) innerExpr = + [ MatchClause(pat, None, TTarget(vspecs, innerExpr, None), pat.Range) ] + +let compileSeqExprMatchClauses (cenv: cenv) env inputExprMark (pat: Pattern, vspecs) innerExpr inputExprOpt bindPatTy genInnerTy = let patMark = pat.Range - let tclauses = mkSeqExprMatchClauses (pat, vspecs) innerExpr - CompilePatternForMatchClauses cenv env inputExprMark patMark false ThrowIncompleteMatchException inputExprOpt bindPatTy genInnerTy tclauses + let tclauses = mkSeqExprMatchClauses (pat, vspecs) innerExpr + + CompilePatternForMatchClauses + cenv + env + inputExprMark + patMark + false + ThrowIncompleteMatchException + inputExprOpt + bindPatTy + genInnerTy + tclauses /// This case is used for computation expressions which are sequence expressions. Technically the code path is different because it /// typechecks rather than doing a shallow syntactic translation, and generates calls into the Seq.* library -/// and helpers rather than to the builder methods (there is actually no builder for 'seq' in the library). -/// These are later detected by state machine compilation. +/// and helpers rather than to the builder methods (there is actually no builder for 'seq' in the library). +/// These are later detected by state machine compilation. /// /// Also "ienumerable extraction" is performed on arguments to "for". -let TcSequenceExpression (cenv: cenv) env tpenv comp (overallTy: OverallTy) m = +let TcSequenceExpression (cenv: cenv) env tpenv comp (overallTy: OverallTy) m = let g = cenv.g let genEnumElemTy = NewInferenceType g @@ -1922,68 +2986,94 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp (overallTy: OverallTy) m = let flex = not (isTyparTy cenv.g genEnumElemTy) // If there are no 'yield' in the computation expression then allow the type-directed rule - // interpreting non-unit-typed expressions in statement positions as 'yield'. 'yield!' may be + // interpreting non-unit-typed expressions in statement positions as 'yield'. 'yield!' may be // present in the computation expression. let enableImplicitYield = cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield && (YieldFree cenv comp) - let mkSeqDelayedExpr m (coreExpr: Expr) = + let mkSeqDelayedExpr m (coreExpr: Expr) = let overallTy = tyOfExpr cenv.g coreExpr mkSeqDelay cenv env m overallTy coreExpr let rec tryTcSequenceExprBody env genOuterTy tpenv comp = - match comp with - | SynExpr.ForEach (spFor, spIn, SeqExprOnly _seqExprOnly, _isFromSource, pat, pseudoEnumExpr, innerComp, _m) -> + match comp with + | SynExpr.ForEach(spFor, spIn, SeqExprOnly _seqExprOnly, _isFromSource, pat, pseudoEnumExpr, innerComp, _m) -> let pseudoEnumExpr = match RewriteRangeExpr pseudoEnumExpr with | Some e -> e | None -> pseudoEnumExpr - // This expression is not checked with the knowledge it is an IEnumerable, since we permit other enumerable types with GetEnumerator/MoveNext methods, as does C# - let pseudoEnumExpr, arbitraryTy, tpenv = TcExprOfUnknownType cenv env tpenv pseudoEnumExpr - let enumExpr, enumElemTy = ConvertArbitraryExprToEnumerable cenv arbitraryTy env pseudoEnumExpr - let patR, _, vspecs, envinner, tpenv = TcMatchPattern cenv enumElemTy env tpenv pat None + // This expression is not checked with the knowledge it is an IEnumerable, since we permit other enumerable types with GetEnumerator/MoveNext methods, as does C# + let pseudoEnumExpr, arbitraryTy, tpenv = + TcExprOfUnknownType cenv env tpenv pseudoEnumExpr + + let enumExpr, enumElemTy = + ConvertArbitraryExprToEnumerable cenv arbitraryTy env pseudoEnumExpr + + let patR, _, vspecs, envinner, tpenv = + TcMatchPattern cenv enumElemTy env tpenv pat None + let innerExpr, tpenv = let envinner = { envinner with eIsControlFlow = true } tcSequenceExprBody envinner genOuterTy tpenv innerComp - + let enumExprRange = enumExpr.Range // We attach the debug point to the lambda expression so we can fetch it out again in LowerComputedListOrArraySeqExpr - let mFor = match spFor with DebugPointAtFor.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.For) | _ -> enumExprRange + let mFor = + match spFor with + | DebugPointAtFor.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.For) + | _ -> enumExprRange // We attach the debug point to the lambda expression so we can fetch it out again in LowerComputedListOrArraySeqExpr - let mIn = match spIn with DebugPointAtInOrTo.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.InOrTo) | _ -> pat.Range + let mIn = + match spIn with + | DebugPointAtInOrTo.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.InOrTo) + | _ -> pat.Range - match patR, vspecs, innerExpr with + match patR, vspecs, innerExpr with // Legacy peephole optimization: // "seq { .. for x in e1 -> e2 .. }" == "e1 |> Seq.map (fun x -> e2)" // "seq { .. for x in e1 do yield e2 .. }" == "e1 |> Seq.map (fun x -> e2)" // // This transformation is visible in quotations and thus needs to remain. - | (TPat_as (TPat_wild _, PatternValBinding (v, _), _), - [_], - DebugPoints(Expr.App (Expr.Val (vref, _, _), _, [genEnumElemTy], [yieldExpr], _mYield), recreate)) - when valRefEq cenv.g vref cenv.g.seq_singleton_vref -> + | (TPat_as(TPat_wild _, PatternValBinding(v, _), _), + [ _ ], + DebugPoints(Expr.App(Expr.Val(vref, _, _), _, [ genEnumElemTy ], [ yieldExpr ], _mYield), recreate)) when + valRefEq cenv.g vref cenv.g.seq_singleton_vref + -> // The debug point mFor is attached to the 'map' // The debug point mIn is attached to the lambda - // Note: the 'yield' part of the debug point for 'yield expr' is currently lost in debug points. + // Note: the 'yield' part of the debug point for 'yield expr' is currently lost in debug points. let lam = mkLambda mIn v (recreate yieldExpr, genEnumElemTy) - let enumExpr = mkCoerceIfNeeded cenv.g (mkSeqTy cenv.g enumElemTy) (tyOfExpr cenv.g enumExpr) enumExpr + + let enumExpr = + mkCoerceIfNeeded cenv.g (mkSeqTy cenv.g enumElemTy) (tyOfExpr cenv.g enumExpr) enumExpr + Some(mkCallSeqMap cenv.g mFor enumElemTy genEnumElemTy lam enumExpr, tpenv) - | _ -> + | _ -> // The debug point mFor is attached to the 'collect' // The debug point mIn is attached to the lambda - let matchv, matchExpr = compileSeqExprMatchClauses cenv env enumExprRange (patR, vspecs) innerExpr None enumElemTy genOuterTy + let matchv, matchExpr = + compileSeqExprMatchClauses cenv env enumExprRange (patR, vspecs) innerExpr None enumElemTy genOuterTy + let lam = mkLambda mIn matchv (matchExpr, tyOfExpr cenv.g matchExpr) Some(mkSeqCollect cenv env mFor enumElemTy genOuterTy lam enumExpr, tpenv) - | SynExpr.For (forDebugPoint=spFor; toDebugPoint=spTo; ident=id; identBody=start; direction=dir; toBody=finish; doBody=innerComp; range=m) -> + | SynExpr.For( + forDebugPoint = spFor + toDebugPoint = spTo + ident = id + identBody = start + direction = dir + toBody = finish + doBody = innerComp + range = m) -> Some(tcSequenceExprBody env genOuterTy tpenv (elimFastIntegerForLoop (spFor, spTo, id, start, dir, finish, innerComp, m))) - | SynExpr.While (spWhile, guardExpr, innerComp, _m) -> + | SynExpr.While(spWhile, guardExpr, innerComp, _m) -> let guardExpr, tpenv = let env = { env with eIsControlFlow = false } TcExpr cenv (MustEqual cenv.g.bool_ty) env tpenv guardExpr @@ -1991,10 +3081,10 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp (overallTy: OverallTy) m = let innerExpr, tpenv = let env = { env with eIsControlFlow = true } tcSequenceExprBody env genOuterTy tpenv innerComp - + let guardExprMark = guardExpr.Range let guardLambdaExpr = mkUnitDelayLambda cenv.g guardExprMark guardExpr - + // We attach the debug point to the lambda expression so we can fetch it out again in LowerComputedListOrArraySeqExpr let mWhile = match spWhile with @@ -2004,78 +3094,105 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp (overallTy: OverallTy) m = let innerDelayedExpr = mkSeqDelayedExpr mWhile innerExpr Some(mkSeqFromFunctions cenv env guardExprMark genOuterTy guardLambdaExpr innerDelayedExpr, tpenv) - | SynExpr.TryFinally (innerComp, unwindExpr, mTryToLast, spTry, spFinally, trivia) -> + | SynExpr.TryFinally(innerComp, unwindExpr, mTryToLast, spTry, spFinally, trivia) -> let env = { env with eIsControlFlow = true } let innerExpr, tpenv = tcSequenceExprBody env genOuterTy tpenv innerComp let unwindExpr, tpenv = TcExpr cenv (MustEqual cenv.g.unit_ty) env tpenv unwindExpr - + // We attach the debug points to the lambda expressions so we can fetch it out again in LowerComputedListOrArraySeqExpr - let mTry = - match spTry with + let mTry = + match spTry with | DebugPointAtTry.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.Try) | _ -> trivia.TryKeyword - let mFinally = - match spFinally with + let mFinally = + match spFinally with | DebugPointAtFinally.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.Finally) | _ -> trivia.FinallyKeyword let innerExpr = mkSeqDelayedExpr mTry innerExpr let unwindExpr = mkUnitDelayLambda cenv.g mFinally unwindExpr - + Some(mkSeqFinally cenv env mTryToLast genOuterTy innerExpr unwindExpr, tpenv) - | SynExpr.Paren (_, _, _, m) when not (cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield)-> - error(Error(FSComp.SR.tcConstructIsAmbiguousInSequenceExpression(), m)) + | SynExpr.Paren(range = m) when not (cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield) -> + error (Error(FSComp.SR.tcConstructIsAmbiguousInSequenceExpression (), m)) - | SynExpr.ImplicitZero m -> - Some(mkSeqEmpty cenv env m genOuterTy, tpenv ) + | SynExpr.ImplicitZero m -> Some(mkSeqEmpty cenv env m genOuterTy, tpenv) - | SynExpr.DoBang (_rhsExpr, m) -> - error(Error(FSComp.SR.tcDoBangIllegalInSequenceExpression(), m)) + | SynExpr.DoBang(_rhsExpr, m) -> error (Error(FSComp.SR.tcDoBangIllegalInSequenceExpression (), m)) - | SynExpr.Sequential (sp, true, innerComp1, innerComp2, m) -> - let env1 = { env with eIsControlFlow = (match sp with DebugPointAtSequential.SuppressNeither | DebugPointAtSequential.SuppressExpr -> true | _ -> false) } + | SynExpr.Sequential(sp, true, innerComp1, innerComp2, m) -> + let env1 = + { env with + eIsControlFlow = + (match sp with + | DebugPointAtSequential.SuppressNeither + | DebugPointAtSequential.SuppressExpr -> true + | _ -> false) + } - let res, tpenv = tcSequenceExprBodyAsSequenceOrStatement env1 genOuterTy tpenv innerComp1 + let res, tpenv = + tcSequenceExprBodyAsSequenceOrStatement env1 genOuterTy tpenv innerComp1 - let env2 = { env with eIsControlFlow = (match sp with DebugPointAtSequential.SuppressNeither | DebugPointAtSequential.SuppressStmt -> true | _ -> false) } + let env2 = + { env with + eIsControlFlow = + (match sp with + | DebugPointAtSequential.SuppressNeither + | DebugPointAtSequential.SuppressStmt -> true + | _ -> false) + } // "expr; cexpr" is treated as sequential execution // "cexpr; cexpr" is treated as append - match res with - | Choice1Of2 innerExpr1 -> + match res with + | Choice1Of2 innerExpr1 -> let innerExpr2, tpenv = tcSequenceExprBody env2 genOuterTy tpenv innerComp2 let innerExpr2 = mkSeqDelayedExpr innerExpr2.Range innerExpr2 Some(mkSeqAppend cenv env innerComp1.Range genOuterTy innerExpr1 innerExpr2, tpenv) - | Choice2Of2 stmt1 -> + | Choice2Of2 stmt1 -> let innerExpr2, tpenv = tcSequenceExprBody env2 genOuterTy tpenv innerComp2 Some(Expr.Sequential(stmt1, innerExpr2, NormalSeq, m), tpenv) - | SynExpr.IfThenElse (guardExpr, thenComp, elseCompOpt, spIfToThen, _isRecovery, mIfToEndOfElseBranch, trivia) -> + | SynExpr.IfThenElse(guardExpr, thenComp, elseCompOpt, spIfToThen, _isRecovery, mIfToEndOfElseBranch, trivia) -> let guardExpr', tpenv = TcExpr cenv (MustEqual cenv.g.bool_ty) env tpenv guardExpr let env = { env with eIsControlFlow = true } let thenExpr, tpenv = tcSequenceExprBody env genOuterTy tpenv thenComp - let elseComp = (match elseCompOpt with Some c -> c | None -> SynExpr.ImplicitZero trivia.IfToThenRange) + + let elseComp = + (match elseCompOpt with + | Some c -> c + | None -> SynExpr.ImplicitZero trivia.IfToThenRange) + let elseExpr, tpenv = tcSequenceExprBody env genOuterTy tpenv elseComp Some(mkCond spIfToThen mIfToEndOfElseBranch genOuterTy guardExpr' thenExpr elseExpr, tpenv) // 'let x = expr in expr' - | SynExpr.LetOrUse (isUse=false (* not a 'use' binding *)) -> - TcLinearExprs - (fun overallTy envinner tpenv e -> tcSequenceExprBody envinner overallTy.Commit tpenv e) - cenv env overallTy - tpenv + | SynExpr.LetOrUse(isUse = false) -> + TcLinearExprs + (fun overallTy envinner tpenv e -> tcSequenceExprBody envinner overallTy.Commit tpenv e) + cenv + env + overallTy + tpenv true - comp - id |> Some + comp + id + |> Some // 'use x = expr in expr' - | SynExpr.LetOrUse (isUse=true; bindings=[SynBinding (kind=SynBindingKind.Normal; headPat=pat; expr=rhsExpr; debugPoint=spBind)]; body=innerComp; range=wholeExprMark) -> + | SynExpr.LetOrUse( + isUse = true + bindings = [ SynBinding(kind = SynBindingKind.Normal; headPat = pat; expr = rhsExpr; debugPoint = spBind) ] + body = innerComp + range = wholeExprMark) -> let bindPatTy = NewInferenceType g let inputExprTy = NewInferenceType g - let pat', _, vspecs, envinner, tpenv = TcMatchPattern cenv bindPatTy env tpenv pat None + + let pat', _, vspecs, envinner, tpenv = + TcMatchPattern cenv bindPatTy env tpenv pat None UnifyTypes cenv env m inputExprTy bindPatTy @@ -2087,84 +3204,117 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp (overallTy: OverallTy) m = let envinner = { envinner with eIsControlFlow = true } tcSequenceExprBody envinner genOuterTy tpenv innerComp - let mBind = - match spBind with + let mBind = + match spBind with | DebugPointAtBinding.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.Binding) | _ -> inputExpr.Range let inputExprMark = inputExpr.Range - let matchv, matchExpr = compileSeqExprMatchClauses cenv envinner inputExprMark (pat', vspecs) innerExpr (Some inputExpr) bindPatTy genOuterTy + let matchv, matchExpr = + compileSeqExprMatchClauses cenv envinner inputExprMark (pat', vspecs) innerExpr (Some inputExpr) bindPatTy genOuterTy let consumeExpr = mkLambda mBind matchv (matchExpr, genOuterTy) // The 'mBind' is attached to the lambda Some(mkSeqUsing cenv env wholeExprMark bindPatTy genOuterTy inputExpr consumeExpr, tpenv) - | SynExpr.LetOrUseBang (range=m) -> - error(Error(FSComp.SR.tcUseForInSequenceExpression(), m)) + | SynExpr.LetOrUseBang(range = m) -> error (Error(FSComp.SR.tcUseForInSequenceExpression (), m)) - | SynExpr.Match (spMatch, expr, clauses, _m, _trivia) -> + | SynExpr.Match(spMatch, expr, clauses, _m, _trivia) -> let inputExpr, inputTy, tpenv = TcExprOfUnknownType cenv env tpenv expr - let tclauses, tpenv = - (tpenv, clauses) ||> List.mapFold (fun tpenv (SynMatchClause(pat, cond, innerComp, _, sp, _)) -> - let patR, condR, vspecs, envinner, tpenv = TcMatchPattern cenv inputTy env tpenv pat cond - let envinner = - match sp with - | DebugPointAtTarget.Yes -> { envinner with eIsControlFlow = true } - | DebugPointAtTarget.No -> envinner - let innerExpr, tpenv = tcSequenceExprBody envinner genOuterTy tpenv innerComp - MatchClause(patR, condR, TTarget(vspecs, innerExpr, None), patR.Range), tpenv) + let tclauses, tpenv = + (tpenv, clauses) + ||> List.mapFold (fun tpenv (SynMatchClause(pat, cond, innerComp, _, sp, _)) -> + let patR, condR, vspecs, envinner, tpenv = + TcMatchPattern cenv inputTy env tpenv pat cond + + let envinner = + match sp with + | DebugPointAtTarget.Yes -> { envinner with eIsControlFlow = true } + | DebugPointAtTarget.No -> envinner + + let innerExpr, tpenv = tcSequenceExprBody envinner genOuterTy tpenv innerComp + MatchClause(patR, condR, TTarget(vspecs, innerExpr, None), patR.Range), tpenv) let inputExprTy = tyOfExpr cenv.g inputExpr let inputExprMark = inputExpr.Range - let matchv, matchExpr = CompilePatternForMatchClauses cenv env inputExprMark inputExprMark true ThrowIncompleteMatchException (Some inputExpr) inputExprTy genOuterTy tclauses + + let matchv, matchExpr = + CompilePatternForMatchClauses + cenv + env + inputExprMark + inputExprMark + true + ThrowIncompleteMatchException + (Some inputExpr) + inputExprTy + genOuterTy + tclauses Some(mkLet spMatch inputExprMark matchv inputExpr matchExpr, tpenv) - | SynExpr.TryWith (innerTry,withList,mTryToWith,_spTry,_spWith,trivia) -> - if not(g.langVersion.SupportsFeature(LanguageFeature.TryWithInSeqExpression)) then - error(Error(FSComp.SR.tcTryIllegalInSequenceExpression(), mTryToWith)) + | SynExpr.TryWith(innerTry, withList, mTryToWith, _spTry, _spWith, trivia) -> + if not (g.langVersion.SupportsFeature(LanguageFeature.TryWithInSeqExpression)) then + error (Error(FSComp.SR.tcTryIllegalInSequenceExpression (), mTryToWith)) let env = { env with eIsControlFlow = true } - let tryExpr, tpenv = - let inner,tpenv = tcSequenceExprBody env genOuterTy tpenv innerTry + + let tryExpr, tpenv = + let inner, tpenv = tcSequenceExprBody env genOuterTy tpenv innerTry mkSeqDelayedExpr mTryToWith inner, tpenv // Compile the pattern twice, once as a filter with all succeeding targets returning "1", and once as a proper catch block. - let clauses, tpenv = - (tpenv, withList) ||> List.mapFold (fun tpenv (SynMatchClause(pat, cond, innerComp, m, sp, _)) -> - let patR, condR, vspecs, envinner, tpenv = TcMatchPattern cenv g.exn_ty env tpenv pat cond + let clauses, tpenv = + (tpenv, withList) + ||> List.mapFold (fun tpenv (SynMatchClause(pat, cond, innerComp, m, sp, _)) -> + let patR, condR, vspecs, envinner, tpenv = + TcMatchPattern cenv g.exn_ty env tpenv pat cond + let envinner = match sp with | DebugPointAtTarget.Yes -> { envinner with eIsControlFlow = true } | DebugPointAtTarget.No -> envinner + let matchBody, tpenv = tcSequenceExprBody envinner genOuterTy tpenv innerComp - let handlerClause = MatchClause(patR, condR, TTarget(vspecs, matchBody, None), patR.Range) - let filterClause = MatchClause(patR, condR, TTarget([], Expr.Const(Const.Int32 1,m,g.int_ty), None), patR.Range) - (handlerClause,filterClause), tpenv) + + let handlerClause = + MatchClause(patR, condR, TTarget(vspecs, matchBody, None), patR.Range) + + let filterClause = + MatchClause(patR, condR, TTarget([], Expr.Const(Const.Int32 1, m, g.int_ty), None), patR.Range) + + (handlerClause, filterClause), tpenv) let handlers, filterClauses = List.unzip clauses let withRange = trivia.WithToEndRange - let v1, filterExpr = CompilePatternForMatchClauses cenv env withRange withRange true FailFilter None g.exn_ty g.int_ty filterClauses - let v2, handlerExpr = CompilePatternForMatchClauses cenv env withRange withRange true FailFilter None g.exn_ty genOuterTy handlers + + let v1, filterExpr = + CompilePatternForMatchClauses cenv env withRange withRange true FailFilter None g.exn_ty g.int_ty filterClauses + + let v2, handlerExpr = + CompilePatternForMatchClauses cenv env withRange withRange true FailFilter None g.exn_ty genOuterTy handlers let filterLambda = mkLambda filterExpr.Range v1 (filterExpr, genOuterTy) let handlerLambda = mkLambda handlerExpr.Range v2 (handlerExpr, genOuterTy) - let combinatorExpr = mkSeqTryWith cenv env mTryToWith genOuterTy tryExpr filterLambda handlerLambda - Some (combinatorExpr,tpenv) + let combinatorExpr = + mkSeqTryWith cenv env mTryToWith genOuterTy tryExpr filterLambda handlerLambda + + Some(combinatorExpr, tpenv) - | SynExpr.YieldOrReturnFrom ((isYield, _), synYieldExpr, m) -> + | SynExpr.YieldOrReturnFrom((isYield, _), synYieldExpr, m) -> let env = { env with eIsControlFlow = false } let resultExpr, genExprTy, tpenv = TcExprOfUnknownType cenv env tpenv synYieldExpr - if not isYield then errorR(Error(FSComp.SR.tcUseYieldBangForMultipleResults(), m)) + if not isYield then + errorR (Error(FSComp.SR.tcUseYieldBangForMultipleResults (), m)) AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace genOuterTy genExprTy - let resultExpr = mkCoerceExpr(resultExpr, genOuterTy, m, genExprTy) + let resultExpr = mkCoerceExpr (resultExpr, genOuterTy, m, genExprTy) let resultExpr = if IsControlFlowExpression synYieldExpr then @@ -2174,11 +3324,12 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp (overallTy: OverallTy) m = Some(resultExpr, tpenv) - | SynExpr.YieldOrReturn ((isYield, _), synYieldExpr, m) -> + | SynExpr.YieldOrReturn((isYield, _), synYieldExpr, m) -> let env = { env with eIsControlFlow = false } let genResultTy = NewInferenceType g - if not isYield then errorR(Error(FSComp.SR.tcSeqResultsUseYield(), m)) + if not isYield then + errorR (Error(FSComp.SR.tcSeqResultsUseYield (), m)) UnifyTypes cenv env m genOuterTy (mkSeqTy cenv.g genResultTy) @@ -2192,30 +3343,34 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp (overallTy: OverallTy) m = else mkDebugPoint m resultExpr - Some(resultExpr, tpenv ) + Some(resultExpr, tpenv) | _ -> None - + and tcSequenceExprBody env (genOuterTy: TType) tpenv comp = - let res, tpenv = tcSequenceExprBodyAsSequenceOrStatement env genOuterTy tpenv comp - match res with - | Choice1Of2 expr -> - expr, tpenv - | Choice2Of2 stmt -> + let res, tpenv = tcSequenceExprBodyAsSequenceOrStatement env genOuterTy tpenv comp + + match res with + | Choice1Of2 expr -> expr, tpenv + | Choice2Of2 stmt -> let m = comp.Range let resExpr = Expr.Sequential(stmt, mkSeqEmpty cenv env m genOuterTy, NormalSeq, m) resExpr, tpenv and tcSequenceExprBodyAsSequenceOrStatement env genOuterTy tpenv comp = - match tryTcSequenceExprBody env genOuterTy tpenv comp with - | Some (expr, tpenv) -> Choice1Of2 expr, tpenv - | None -> + match tryTcSequenceExprBody env genOuterTy tpenv comp with + | Some(expr, tpenv) -> Choice1Of2 expr, tpenv + | None -> - let env = { env with eContextInfo = ContextInfo.SequenceExpression genOuterTy } + let env = + { env with + eContextInfo = ContextInfo.SequenceExpression genOuterTy + } if enableImplicitYield then let hasTypeUnit, expr, tpenv = TryTcStmt cenv env tpenv comp - if hasTypeUnit then + + if hasTypeUnit then Choice2Of2 expr, tpenv else let genResultTy = NewInferenceType g @@ -2224,7 +3379,10 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp (overallTy: OverallTy) m = let expr, tpenv = TcExprFlex cenv flex true genResultTy env tpenv comp let exprTy = tyOfExpr cenv.g expr AddCxTypeMustSubsumeType env.eContextInfo env.DisplayEnv cenv.css mExpr NoTrace genResultTy exprTy - let resExpr = mkCallSeqSingleton cenv.g mExpr genResultTy (mkCoerceExpr(expr, genResultTy, mExpr, exprTy)) + + let resExpr = + mkCallSeqSingleton cenv.g mExpr genResultTy (mkCoerceExpr (expr, genResultTy, mExpr, exprTy)) + Choice1Of2 resExpr, tpenv else let stmt, tpenv = TcStmtThatCantBeCtorBody cenv env tpenv comp @@ -2236,28 +3394,32 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp (overallTy: OverallTy) m = let TcSequenceExpressionEntry (cenv: cenv) env (overallTy: OverallTy) tpenv (hasBuilder, comp) m = match RewriteRangeExpr comp with - | Some replacementExpr -> - TcExpr cenv overallTy env tpenv replacementExpr + | Some replacementExpr -> TcExpr cenv overallTy env tpenv replacementExpr | None -> - let implicitYieldEnabled = cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield + let implicitYieldEnabled = + cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield - let validateObjectSequenceOrRecordExpression = not implicitYieldEnabled + let validateObjectSequenceOrRecordExpression = not implicitYieldEnabled - match comp with - | SynExpr.New _ -> - errorR(Error(FSComp.SR.tcInvalidObjectExpressionSyntaxForm(), m)) - | SimpleSemicolonSequence cenv false _ when validateObjectSequenceOrRecordExpression -> - errorR(Error(FSComp.SR.tcInvalidObjectSequenceOrRecordExpression(), m)) - | _ -> - () + match comp with + | SynExpr.New _ -> + try + TcExprUndelayed cenv overallTy env tpenv comp |> ignore + with RecoverableException e -> + errorRecovery e m + + errorR (Error(FSComp.SR.tcInvalidObjectExpressionSyntaxForm (), m)) + | SimpleSemicolonSequence cenv false _ when validateObjectSequenceOrRecordExpression -> + errorR (Error(FSComp.SR.tcInvalidObjectSequenceOrRecordExpression (), m)) + | _ -> () - if not hasBuilder && not cenv.g.compilingFSharpCore then - error(Error(FSComp.SR.tcInvalidSequenceExpressionSyntaxForm(), m)) - - TcSequenceExpression cenv env tpenv comp overallTy m + if not hasBuilder && not cenv.g.compilingFSharpCore then + error (Error(FSComp.SR.tcInvalidSequenceExpressionSyntaxForm (), m)) -let TcArrayOrListComputedExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (isArray, comp) m = + TcSequenceExpression cenv env tpenv comp overallTy m + +let TcArrayOrListComputedExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (isArray, comp) m = let g = cenv.g // The syntax '[ n .. m ]' and '[ n .. step .. m ]' is not really part of array or list syntax. @@ -2265,7 +3427,7 @@ let TcArrayOrListComputedExpression (cenv: cenv) env (overallTy: OverallTy) tpen // // The elaborated form of '[ n .. m ]' is 'List.ofSeq (seq (op_Range n m))' and this shouldn't change match RewriteRangeExpr comp with - | Some replacementExpr -> + | Some replacementExpr -> let genCollElemTy = NewInferenceType g let genCollTy = (if isArray then mkArrayType else mkListTy) cenv.g genCollElemTy @@ -2276,87 +3438,131 @@ let TcArrayOrListComputedExpression (cenv: cenv) env (overallTy: OverallTy) tpen let expr, tpenv = TcExpr cenv (MustEqual exprTy) env tpenv replacementExpr - let expr = - if cenv.g.compilingFSharpCore then - expr - else + let expr = + if cenv.g.compilingFSharpCore then + expr + else // We add a call to 'seq ... ' to make sure sequence expression compilation gets applied to the contents of the // comprehension. But don't do this in FSharp.Core.dll since 'seq' may not yet be defined. mkCallSeq cenv.g m genCollElemTy expr - - let expr = mkCoerceExpr(expr, exprTy, expr.Range, overallTy.Commit) - let expr = - if isArray then + let expr = mkCoerceExpr (expr, exprTy, expr.Range, overallTy.Commit) + + let expr = + if isArray then mkCallSeqToArray cenv.g m genCollElemTy expr - else + else mkCallSeqToList cenv.g m genCollElemTy expr + expr, tpenv | None -> - // LanguageFeatures.ImplicitYield do not require this validation - let implicitYieldEnabled = cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield - let validateExpressionWithIfRequiresParenthesis = not implicitYieldEnabled - let acceptDeprecatedIfThenExpression = not implicitYieldEnabled + // LanguageFeatures.ImplicitYield do not require this validation + let implicitYieldEnabled = + cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield + + let validateExpressionWithIfRequiresParenthesis = not implicitYieldEnabled + let acceptDeprecatedIfThenExpression = not implicitYieldEnabled - match comp with - | SimpleSemicolonSequence cenv acceptDeprecatedIfThenExpression elems -> match comp with - | SimpleSemicolonSequence cenv false _ -> () - | _ when validateExpressionWithIfRequiresParenthesis -> errorR(Deprecated(FSComp.SR.tcExpressionWithIfRequiresParenthesis(), m)) - | _ -> () + | SimpleSemicolonSequence cenv acceptDeprecatedIfThenExpression elems -> + match comp with + | SimpleSemicolonSequence cenv false _ -> () + | _ when validateExpressionWithIfRequiresParenthesis -> + errorR (Deprecated(FSComp.SR.tcExpressionWithIfRequiresParenthesis (), m)) + | _ -> () - let replacementExpr = - if isArray then - // This are to improve parsing/processing speed for parser tables by converting to an array blob ASAP - let nelems = elems.Length - if nelems > 0 && List.forall (function SynExpr.Const (SynConst.UInt16 _, _) -> true | _ -> false) elems - then SynExpr.Const (SynConst.UInt16s (Array.ofList (List.map (function SynExpr.Const (SynConst.UInt16 x, _) -> x | _ -> failwith "unreachable") elems)), m) - elif nelems > 0 && List.forall (function SynExpr.Const (SynConst.Byte _, _) -> true | _ -> false) elems - then SynExpr.Const (SynConst.Bytes (Array.ofList (List.map (function SynExpr.Const (SynConst.Byte x, _) -> x | _ -> failwith "unreachable") elems), SynByteStringKind.Regular, m), m) - else SynExpr.ArrayOrList (isArray, elems, m) - else - if cenv.g.langVersion.SupportsFeature(LanguageFeature.ReallyLongLists) then - SynExpr.ArrayOrList (isArray, elems, m) - else - if elems.Length > 500 then - error(Error(FSComp.SR.tcListLiteralMaxSize(), m)) - SynExpr.ArrayOrList (isArray, elems, m) + let replacementExpr = + if isArray then + // This are to improve parsing/processing speed for parser tables by converting to an array blob ASAP + let nelems = elems.Length + + if + nelems > 0 + && List.forall + (function + | SynExpr.Const(SynConst.UInt16 _, _) -> true + | _ -> false) + elems + then + SynExpr.Const( + SynConst.UInt16s( + Array.ofList ( + List.map + (function + | SynExpr.Const(SynConst.UInt16 x, _) -> x + | _ -> failwith "unreachable") + elems + ) + ), + m + ) + elif + nelems > 0 + && List.forall + (function + | SynExpr.Const(SynConst.Byte _, _) -> true + | _ -> false) + elems + then + SynExpr.Const( + SynConst.Bytes( + Array.ofList ( + List.map + (function + | SynExpr.Const(SynConst.Byte x, _) -> x + | _ -> failwith "unreachable") + elems + ), + SynByteStringKind.Regular, + m + ), + m + ) + else + SynExpr.ArrayOrList(isArray, elems, m) + else if cenv.g.langVersion.SupportsFeature(LanguageFeature.ReallyLongLists) then + SynExpr.ArrayOrList(isArray, elems, m) + else + if elems.Length > 500 then + error (Error(FSComp.SR.tcListLiteralMaxSize (), m)) - TcExprUndelayed cenv overallTy env tpenv replacementExpr - | _ -> + SynExpr.ArrayOrList(isArray, elems, m) - let genCollElemTy = NewInferenceType g + TcExprUndelayed cenv overallTy env tpenv replacementExpr + | _ -> - let genCollTy = (if isArray then mkArrayType else mkListTy) cenv.g genCollElemTy + let genCollElemTy = NewInferenceType g - // Propagating type directed conversion, e.g. for - // let x : seq = [ yield 1; if true then yield 2 ] - TcPropagatingExprLeafThenConvert cenv overallTy genCollTy env (* canAdhoc *) m (fun () -> - - let exprTy = mkSeqTy cenv.g genCollElemTy + let genCollTy = (if isArray then mkArrayType else mkListTy) cenv.g genCollElemTy - // Check the comprehension - let expr, tpenv = TcSequenceExpression cenv env tpenv comp (MustEqual exprTy) m + // Propagating type directed conversion, e.g. for + // let x : seq = [ yield 1; if true then yield 2 ] + TcPropagatingExprLeafThenConvert cenv overallTy genCollTy env (* canAdhoc *) m (fun () -> - let expr = mkCoerceIfNeeded cenv.g exprTy (tyOfExpr cenv.g expr) expr + let exprTy = mkSeqTy cenv.g genCollElemTy - let expr = - if cenv.g.compilingFSharpCore then - //warning(Error(FSComp.SR.fslibUsingComputedListOrArray(), expr.Range)) - expr - else - // We add a call to 'seq ... ' to make sure sequence expression compilation gets applied to the contents of the - // comprehension. But don't do this in FSharp.Core.dll since 'seq' may not yet be defined. - mkCallSeq cenv.g m genCollElemTy expr - - let expr = mkCoerceExpr(expr, exprTy, expr.Range, overallTy.Commit) + // Check the comprehension + let expr, tpenv = TcSequenceExpression cenv env tpenv comp (MustEqual exprTy) m - let expr = - if isArray then - mkCallSeqToArray cenv.g m genCollElemTy expr - else - mkCallSeqToList cenv.g m genCollElemTy expr - - expr, tpenv) + let expr = mkCoerceIfNeeded cenv.g exprTy (tyOfExpr cenv.g expr) expr + + let expr = + if cenv.g.compilingFSharpCore then + //warning(Error(FSComp.SR.fslibUsingComputedListOrArray(), expr.Range)) + expr + else + // We add a call to 'seq ... ' to make sure sequence expression compilation gets applied to the contents of the + // comprehension. But don't do this in FSharp.Core.dll since 'seq' may not yet be defined. + mkCallSeq cenv.g m genCollElemTy expr + + let expr = mkCoerceExpr (expr, exprTy, expr.Range, overallTy.Commit) + + let expr = + if isArray then + mkCallSeqToArray cenv.g m genCollElemTy expr + else + mkCallSeqToList cenv.g m genCollElemTy expr + + expr, tpenv) diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index 1a958832ce6..469b1ab4ee3 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -866,7 +866,8 @@ module AddAugmentationDeclarations = let ShouldAugmentUnion (g: TcGlobals) (tycon: Tycon) = g.langVersion.SupportsFeature LanguageFeature.UnionIsPropertiesVisible && - HasDefaultAugmentationAttribute g (mkLocalTyconRef tycon) + HasDefaultAugmentationAttribute g (mkLocalTyconRef tycon) && + tycon.UnionCasesArray.Length > 1 let AddUnionAugmentationValues (cenv: cenv) (env: TcEnv) tycon = let tcref = mkLocalTyconRef tycon @@ -1039,7 +1040,7 @@ module MutRecBindingChecking = let innerState = (None, envForTycon, tpenv, recBindIdx, uncheckedBindsRev) [Phase2AIncrClassCtor (staticCtorInfo, None)], innerState - | Some (SynMemberDefn.ImplicitCtor (vis, Attributes attrs, SynSimplePats.SimplePats(pats=spats), thisIdOpt, xmlDoc, m,_)), ContainerInfo(_, Some memberContainerInfo) -> + | Some (SynMemberDefn.ImplicitCtor (vis, Attributes attrs, pat, thisIdOpt, xmlDoc, m,_)), ContainerInfo(_, Some memberContainerInfo) -> let (MemberOrValContainerInfo(tcref, _, baseValOpt, safeInitInfo, _)) = memberContainerInfo @@ -1050,7 +1051,7 @@ module MutRecBindingChecking = let staticCtorInfo = TcStaticImplicitCtorInfo_Phase2A(cenv, envForTycon, tcref, m, copyOfTyconTypars) // Phase2A: make incrCtorInfo - ctorv, thisVal etc, type depends on argty(s) - let incrCtorInfo = TcImplicitCtorInfo_Phase2A(cenv, envForTycon, tpenv, tcref, vis, attrs, spats, thisIdOpt, baseValOpt, safeInitInfo, m, copyOfTyconTypars, objTy, thisTy, xmlDoc) + let incrCtorInfo = TcImplicitCtorInfo_Phase2A(cenv, envForTycon, tpenv, tcref, vis, attrs, pat, thisIdOpt, baseValOpt, safeInitInfo, m, copyOfTyconTypars, objTy, thisTy, xmlDoc) // Phase2A: Add copyOfTyconTypars from incrCtorInfo - or from tcref let envForTycon = AddDeclaredTypars CheckForDuplicateTypars staticCtorInfo.IncrCtorDeclaredTypars envForTycon @@ -1203,11 +1204,13 @@ module MutRecBindingChecking = if cenv.g.langVersion.SupportsFeature(LanguageFeature.CSharpExtensionAttributeNotRequired) then tyconOpt |> Option.map (fun tycon -> - tryAddExtensionAttributeIfNotAlreadyPresent + tryAddExtensionAttributeIfNotAlreadyPresentForType + g (fun tryFindExtensionAttribute -> tycon.MembersOfFSharpTyconSorted |> Seq.tryPick (fun m -> tryFindExtensionAttribute m.Attribs) ) + envForTycon.eModuleOrNamespaceTypeAccumulator tycon ) else @@ -1332,10 +1335,10 @@ module MutRecBindingChecking = // Phase2B: typecheck the argument to an 'inherits' call and build the new object expr for the inherit-call | Phase2AInherit (synBaseTy, arg, baseValOpt, m) -> - let baseTy, tpenv = TcType cenv NoNewTypars CheckCxs ItemOccurence.Use WarnOnIWSAM.Yes envInstance tpenv synBaseTy - let baseTy = baseTy |> convertToTypeWithMetadataIfPossible g let inheritsExpr, tpenv = - try + try + let baseTy, tpenv = TcType cenv NoNewTypars CheckCxs ItemOccurence.Use WarnOnIWSAM.Yes envInstance tpenv synBaseTy + let baseTy = baseTy |> convertToTypeWithMetadataIfPossible g TcNewExpr cenv envInstance tpenv baseTy (Some synBaseTy.Range) true arg m with RecoverableException e -> errorRecovery e m @@ -1437,7 +1440,25 @@ module MutRecBindingChecking = let innerState = (tpenv, envInstance, envStatic, envNonRec, generalizedRecBinds, preGeneralizationRecBinds, uncheckedRecBindsTable) Phase2BMember rbind.RecBindingInfo.Index, innerState) - + + let tyconOpt = + if not(cenv.g.langVersion.SupportsFeature(LanguageFeature.CSharpExtensionAttributeNotRequired)) then + tyconOpt + else + // We need to redo this check, which already happened in TcMutRecBindings_Phase2A_CreateRecursiveValuesAndCheckArgumentPatterns + // Because the environment is being reset in the case of recursive modules. + tyconOpt + |> Option.map (fun tycon -> + tryAddExtensionAttributeIfNotAlreadyPresentForType + g + (fun tryFindExtensionAttribute -> + tycon.MembersOfFSharpTyconSorted + |> Seq.tryPick (fun m -> tryFindExtensionAttribute m.Attribs) + ) + envForTycon.eModuleOrNamespaceTypeAccumulator + tycon + ) + let defnBs = MutRecShape.Tycon (TyconBindingsPhase2B(tyconOpt, tcref, defnBs)) let outerState = (tpenv, generalizedRecBinds, preGeneralizationRecBinds, uncheckedRecBindsTable, envNonRec) defnBs, outerState) @@ -1906,9 +1927,10 @@ module MutRecBindingChecking = let private ReportErrorOnStaticClass (synMembers: SynMemberDefn list) = for mem in synMembers do match mem with - | SynMemberDefn.ImplicitCtor(ctorArgs = SynSimplePats.SimplePats(pats = pats)) when (not pats.IsEmpty) -> - for pat in pats do - warning(Error(FSComp.SR.chkConstructorWithArgumentsOnStaticClasses(), pat.Range)) + | SynMemberDefn.ImplicitCtor(ctorArgs = pat) -> + match pat with + | SynPat.Paren(innerPat, _) -> warning(Error(FSComp.SR.chkConstructorWithArgumentsOnStaticClasses(), innerPat.Range)) + | _ -> () | SynMemberDefn.Member(SynBinding(valData = SynValData(memberFlags = Some memberFlags)), m) when memberFlags.MemberKind = SynMemberKind.Constructor -> warning(Error(FSComp.SR.chkAdditionalConstructorOnStaticClasses(), m)) | SynMemberDefn.Member(SynBinding(valData = SynValData(memberFlags = Some memberFlags)), m) when memberFlags.IsInstance -> @@ -2475,7 +2497,7 @@ module TcExceptionDeclarations = let TcExnSignature (cenv: cenv) envInitial parent tpenv (SynExceptionSig(exnRepr=core; members=aug), scopem) = match core with - | SynExceptionDefnRepr(caseName = SynUnionCase(ident = SynIdent(ident, _))) when ident.idText = "" -> + | SynExceptionDefnRepr(caseName = SynUnionCase(ident = SynIdent(ident, _))) when String.IsNullOrEmpty(ident.idText) -> [], [], None, envInitial | _ -> let g = cenv.g @@ -2603,8 +2625,8 @@ module EstablishTypeDefinitionCores = match implicitCtorSynPats with | None -> () - | Some spats -> - let ctorArgNames, patEnv = TcSimplePatsOfUnknownType cenv true NoCheckCxs env tpenv spats + | Some pat -> + let ctorArgNames, patEnv, _ = TcSimplePatsOfUnknownType cenv true NoCheckCxs env tpenv pat let (TcPatLinearEnv(_, names, _)) = patEnv @@ -2770,19 +2792,24 @@ module EstablishTypeDefinitionCores = match synTyconRepr with | SynTypeDefnSimpleRepr.General (SynTypeDefnKind.Delegate (_ty, arity), _, _, _, _, _, _, _) -> arity.ArgNames | SynTypeDefnSimpleRepr.General (SynTypeDefnKind.Unspecified, _, _, _, _, _, Some synPats, _) -> - let rec patName (p: SynSimplePat) = + let rec patName (p: SynPat) = match p with - | SynSimplePat.Id (id, _, _, _, _, _) -> id.idText - | SynSimplePat.Typed(pat, _, _) -> patName pat - | SynSimplePat.Attrib(pat, _, _) -> patName pat + | SynPat.Named(ident = (SynIdent(id, _))) -> Some id.idText + | SynPat.Typed(pat = pat) + | SynPat.Attrib(pat = pat) -> patName pat + | _ -> None - let rec pats (p: SynSimplePats) = - match p with - | SynSimplePats.SimplePats (pats = ps) -> ps + let getSimplePats (pat: SynPat) = + match pat with + | SynPat.Paren(pat, _) -> + match pat with + | SynPat.Tuple(false, pats, _, _) -> pats + | pat -> [pat] + | _ -> [] let patNames = - pats synPats - |> List.map patName + getSimplePats synPats + |> List.choose patName patNames | _ -> [] @@ -2915,7 +2942,7 @@ module EstablishTypeDefinitionCores = | Some (tc, args, m) -> let ad = envinner.AccessRights match ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.UseInType OpenQualified envinner.NameEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.Yes with - | Result (_, tcrefBeforeStaticArguments) when + | Result (_, tcrefBeforeStaticArguments, _) when tcrefBeforeStaticArguments.IsProvided && not tcrefBeforeStaticArguments.IsErased -> @@ -3357,14 +3384,13 @@ module EstablishTypeDefinitionCores = | rf :: _ -> errorR (Error(FSComp.SR.tcInterfaceTypesAndDelegatesCannotContainFields(), rf.Range)) | _ -> () - let primaryConstructorInDelegateCheck(implicitCtorSynPats : SynSimplePats option) = + let primaryConstructorInDelegateCheck(implicitCtorSynPats : SynPat option) = match implicitCtorSynPats with | None -> () - | Some spats -> - let ctorArgNames, _ = TcSimplePatsOfUnknownType cenv true CheckCxs envinner tpenv spats + | Some pat -> + let ctorArgNames, _, _ = TcSimplePatsOfUnknownType cenv true CheckCxs envinner tpenv pat if not ctorArgNames.IsEmpty then - match spats with - | SynSimplePats.SimplePats(range = m) -> errorR (Error(FSComp.SR.parsOnlyClassCanTakeValueArguments(), m)) + errorR (Error(FSComp.SR.parsOnlyClassCanTakeValueArguments(), pat.Range)) let envinner = AddDeclaredTypars CheckForDuplicateTypars (tycon.Typars m) envinner let envinner = MakeInnerEnvForTyconRef envinner thisTyconRef false @@ -3518,9 +3544,9 @@ module EstablishTypeDefinitionCores = match implicitCtorSynPats with | None -> () - | Some spats -> - if tycon.IsFSharpStructOrEnumTycon then - let ctorArgNames, patEnv = TcSimplePatsOfUnknownType cenv true CheckCxs envinner tpenv spats + | Some pat -> + if tycon.IsFSharpStructOrEnumTycon then + let ctorArgNames, patEnv, _ = TcSimplePatsOfUnknownType cenv true CheckCxs envinner tpenv pat let (TcPatLinearEnv(_, names, _)) = patEnv @@ -4091,11 +4117,11 @@ module TcDeclarations = | _ -> let resInfo = TypeNameResolutionStaticArgsInfo.FromTyArgs synTypars.Length - let _, tcref = + let tcref = match ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.Binding OpenQualified envForDecls.NameEnv ad longPath resInfo PermitDirectReferenceToGeneratedType.No with | Result res -> // Update resolved type parameters with the names from the source. - let _, tcref = res + let _, tcref, _ = res if tcref.TyparsNoRange.Length = synTypars.Length then (tcref.TyparsNoRange, synTypars) ||> List.zip @@ -4105,11 +4131,12 @@ module TcDeclarations = typar.SetIdent(untypedIdent) ) - res - | res when inSig && List.isSingleton longPath -> - errorR(Deprecated(FSComp.SR.tcReservedSyntaxForAugmentation(), m)) - ForceRaise res - | res -> ForceRaise res + tcref + + | Exception exn -> + if inSig && List.isSingleton longPath then + errorR(Deprecated(FSComp.SR.tcReservedSyntaxForAugmentation(), m)) + ForceRaise (Exception exn) tcref let isInterfaceOrDelegateOrEnum = @@ -4285,7 +4312,7 @@ module TcDeclarations = // Convert auto properties to let bindings in the pre-list let rec preAutoProps memb = match memb with - | SynMemberDefn.AutoProperty(ident = id) when id.idText = "" -> [] + | SynMemberDefn.AutoProperty(ident = id) when String.IsNullOrEmpty(id.idText) -> [] | SynMemberDefn.AutoProperty(attributes=Attributes attribs; isStatic=isStatic; ident=id; typeOpt=tyOpt; propKind=propKind; xmlDoc=xmlDoc; synExpr=synExpr; range=mWholeAutoProp) -> // Only the keep the field-targeted attributes let attribs = attribs |> List.filter (fun a -> match a.Target with Some t when t.idText = "field" -> true | _ -> false) @@ -4313,7 +4340,7 @@ module TcDeclarations = // Convert auto properties to member bindings in the post-list let rec postAutoProps memb = match memb with - | SynMemberDefn.AutoProperty(ident = id) when id.idText = "" -> [] + | SynMemberDefn.AutoProperty(ident = id) when String.IsNullOrEmpty(id.idText) -> [] | SynMemberDefn.AutoProperty(attributes=Attributes attribs; isStatic=isStatic; ident=id; typeOpt=tyOpt; propKind=propKind; memberFlags=memberFlags; memberFlagsForSet=memberFlagsForSet; xmlDoc=xmlDoc; accessibility=access; trivia = { GetSetKeywords = mGetSetOpt }) -> let mMemberPortion = id.idRange // Only the keep the non-field-targeted attributes @@ -4420,7 +4447,7 @@ module TcDeclarations = let implicitCtorSynPats = members |> List.tryPick (function - | SynMemberDefn.ImplicitCtor (ctorArgs = SynSimplePats.SimplePats _ as spats) -> Some spats + | SynMemberDefn.ImplicitCtor (ctorArgs = pat) -> Some pat | _ -> None) // An ugly bit of code to pre-determine if a type has a nullary constructor, prior to establishing the @@ -4429,7 +4456,7 @@ module TcDeclarations = members |> List.exists (function | SynMemberDefn.Member(memberDefn=SynBinding(valData=SynValData(memberFlags=Some memberFlags); headPat = SynPatForConstructorDecl SynPatForNullaryArgs)) -> memberFlags.MemberKind=SynMemberKind.Constructor - | SynMemberDefn.ImplicitCtor (ctorArgs = SynSimplePats.SimplePats(pats = spats)) -> isNil spats + | SynMemberDefn.ImplicitCtor (ctorArgs = SynPat.Const(SynConst.Unit, _)) -> true | _ -> false) let repr = SynTypeDefnSimpleRepr.General(kind, inherits, slotsigs, fields, isConcrete, isIncrClass, implicitCtorSynPats, m) let isAtOriginalTyconDefn = not (isAugmentationTyconDefnRepr repr) @@ -4535,16 +4562,20 @@ module TcDeclarations = |> List.map (function | MutRecShape.Tycon (Some tycon, bindings) -> let tycon = - tryAddExtensionAttributeIfNotAlreadyPresent + tryAddExtensionAttributeIfNotAlreadyPresentForType + g (fun tryFindExtensionAttribute -> tycon.MembersOfFSharpTyconSorted |> Seq.tryPick (fun m -> tryFindExtensionAttribute m.Attribs) ) + envFinal.eModuleOrNamespaceTypeAccumulator tycon + MutRecShape.Tycon (Some tycon, bindings) | MutRecShape.Module ((MutRecDefnsPhase2DataForModule(moduleOrNamespaceType, entity), env), shapes) -> let entity = - tryAddExtensionAttributeIfNotAlreadyPresent + tryAddExtensionAttributeIfNotAlreadyPresentForModule + g (fun tryFindExtensionAttribute -> moduleOrNamespaceType.Value.AllValsAndMembers |> Seq.filter(fun v -> v.IsModuleBinding) @@ -4666,8 +4697,28 @@ module TcDeclarations = let envForTycon = AddDeclaredTypars CheckForDuplicateTypars declaredTyconTypars envForDecls let envForTycon = MakeInnerEnvForTyconRef envForTycon tcref (declKind = ExtrinsicExtensionBinding) - TcTyconMemberSpecs cenv envForTycon (TyconContainerInfo(innerParent, tcref, declaredTyconTypars, NoSafeInitInfo)) declKind tpenv members) + let vals, env = TcTyconMemberSpecs cenv envForTycon (TyconContainerInfo(innerParent, tcref, declaredTyconTypars, NoSafeInitInfo)) declKind tpenv members + if not(cenv.g.langVersion.SupportsFeature(LanguageFeature.CSharpExtensionAttributeNotRequired)) then + vals, env + else + // Check if any of the vals has the `[]` attribute + // If this is the case, add it to the type in the env. + let extensionAttributeOnVals = + vals + |> List.tryPick (fun v -> tryFindExtensionAttribute g v.Attribs) + + let typeEntity = + envForTycon.eModuleOrNamespaceTypeAccumulator.Value.AllEntitiesByLogicalMangledName.TryFind(tcref.LogicalName) + + match extensionAttributeOnVals, typeEntity with + | Some extensionAttribute, Some typeEntity -> + if Option.isNone (tryFindExtensionAttribute g typeEntity.Attribs) then + typeEntity.entity_attribs <- extensionAttribute :: typeEntity.Attribs + | _ -> () + vals, env + + ) // Do this for each 'val' declaration in a module (fun envForDecls (containerInfo, valSpec) -> let tpenv = emptyUnscopedTyparEnv @@ -4707,18 +4758,6 @@ module TcDeclarations = // Updates the types of the modules to contain the contents so far, which now includes values and members MutRecBindingChecking.TcMutRecDefns_UpdateModuleContents mutRecNSInfo mutRecDefnsAfterVals - // Generate the union augmentation values for all tycons. - // TODO nullness :: this is the handling of DU .Is* properties WITHIN signature files. - // Watch https://github.com/fsharp/fslang-design/discussions - //(envMutRec, mutRecDefnsAfterCore) ||> MutRecShapes.iterTyconsWithEnv (fun envForDecls ((tyconCore, _, _), tyconOpt, _, _, _) -> - // let (MutRecDefnsPhase1DataForTycon (isAtOriginalTyconDefn=isAtOriginalTyconDefn)) = tyconCore - // match tyconOpt with - // | Some tycon when isAtOriginalTyconDefn -> - // if tycon.IsUnionTycon && AddAugmentationDeclarations.ShouldAugmentUnion cenv.g tycon then - // let vspecs = AddAugmentationDeclarations.AddUnionAugmentationValues cenv envForDecls tycon - // ignore vspecs - // | _ -> ()) - envMutRec //------------------------------------------------------------------------- @@ -5030,7 +5069,7 @@ let rec TcModuleOrNamespaceElementNonMutRec (cenv: cenv) parent typeNames scopem return ([], [], []), env, env | SynModuleDecl.Exception (SynExceptionDefn(SynExceptionDefnRepr(caseName = SynUnionCase(ident = SynIdent(id, _))) as exnRepr, withKeyword, ms, mExDefn), m) -> - if id.idText = "" then + if String.IsNullOrEmpty(id.idText) then return ([], [], []), env, env else let edef = SynExceptionDefn(exnRepr, withKeyword, desugarGetSetMembers ms, mExDefn) @@ -5139,7 +5178,8 @@ let rec TcModuleOrNamespaceElementNonMutRec (cenv: cenv) parent typeNames scopem // //[] //let PlusOne (a:int) = a + 1 - tryAddExtensionAttributeIfNotAlreadyPresent + tryAddExtensionAttributeIfNotAlreadyPresentForModule + g (fun tryFindExtensionAttribute -> match moduleContents with | ModuleOrNamespaceContents.TMDefs(defs) -> @@ -5533,7 +5573,7 @@ let CheckValueRestriction denvAtEnd infoReader rootSigOpt implFileTypePriorToSig // for example FSharp 1.0 3661. (match v.ValReprInfo with None -> true | Some tvi -> tvi.HasNoArgs)) then match ftyvs with - | tp :: _ -> errorR (ValueRestriction(denvAtEnd, infoReader, false, v, tp, v.Range)) + | tp :: _ -> errorR (ValueRestriction(denvAtEnd, infoReader, v, tp, v.Range)) | _ -> () mty.ModuleAndNamespaceDefinitions |> List.iter (fun v -> check v.ModuleOrNamespaceType) try check implFileTypePriorToSig with RecoverableException e -> errorRecovery e m @@ -5546,7 +5586,7 @@ let SolveInternalUnknowns g (cenv: cenv) denvAtEnd moduleContents extraAttribs = if (tp.Rigidity <> TyparRigidity.Rigid) && not tp.IsSolved then ChooseTyparSolutionAndSolve cenv.css denvAtEnd tp -let CheckModuleSignature g (cenv: cenv) m denvAtEnd rootSigOpt implFileTypePriorToSig implFileSpecPriorToSig moduleContents = +let CheckModuleSignature g (cenv: cenv) m denvAtEnd rootSigOpt implFileTypePriorToSig implFileSpecPriorToSig moduleContents fileName qualifiedNameOfFile = match rootSigOpt with | None -> // Deep copy the inferred type of the module @@ -5554,7 +5594,13 @@ let CheckModuleSignature g (cenv: cenv) m denvAtEnd rootSigOpt implFileTypePrior (implFileTypePriorToSigCopied, moduleContents) - | Some sigFileType -> + | Some sigFileType -> + use _ = + Activity.start "CheckDeclarations.CheckModuleSignature" + [| + Activity.Tags.fileName, fileName + Activity.Tags.qualifiedNameOfFile, qualifiedNameOfFile + |] // We want to show imperative type variables in any types in error messages at this late point let denv = { denvAtEnd with showInferenceTyparAnnotations=true } @@ -5680,7 +5726,7 @@ let CheckOneImplFile // Check the module matches the signature let implFileTy, implFileContents = conditionallySuppressErrorReporting (checkForErrors()) (fun () -> - CheckModuleSignature g cenv m denvAtEnd rootSigOpt implFileTypePriorToSig implFileSpecPriorToSig moduleContents) + CheckModuleSignature g cenv m denvAtEnd rootSigOpt implFileTypePriorToSig implFileSpecPriorToSig moduleContents fileName qualNameOfFile.Text) do conditionallySuppressErrorReporting (checkForErrors()) (fun () -> @@ -5700,6 +5746,12 @@ let CheckOneImplFile try let reportErrors = not (checkForErrors()) let tcVal = LightweightTcValForUsingInBuildMethodCall g + use _ = + Activity.start "PostTypeCheckSemanticChecks.CheckImplFile" + [| + Activity.Tags.fileName, fileName + Activity.Tags.qualifiedNameOfFile, qualNameOfFile.Text + |] PostTypeCheckSemanticChecks.CheckImplFile (g, cenv.amap, reportErrors, cenv.infoReader, env.eInternalsVisibleCompPaths, cenv.thisCcu, tcVal, envAtEnd.DisplayEnv, diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index ec76756ef5e..ebf81a3ecd8 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -94,7 +94,7 @@ exception UnionPatternsBindDifferentNames of range exception VarBoundTwice of Ident -exception ValueRestriction of DisplayEnv * InfoReader * bool * Val * Typar * range +exception ValueRestriction of DisplayEnv * InfoReader * Val * Typar * range exception ValNotMutable of DisplayEnv * ValRef * range @@ -767,7 +767,7 @@ let TcConst (cenv: cenv) (overallTy: TType) m env synConst = | SynMeasure.One _ -> Measure.One | SynMeasure.Named(tc, m) -> let ad = env.eAccessRights - let _, tcref = ForceRaise(ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.Use OpenQualified env.eNameResEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No) + let _, tcref, _ = ForceRaise(ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.Use OpenQualified env.eNameResEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No) match tcref.TypeOrMeasureKind with | TyparKind.Type -> error(Error(FSComp.SR.tcExpectedUnitOfMeasureNotType(), m)) | TyparKind.Measure -> Measure.Const tcref @@ -3152,15 +3152,17 @@ let BuildRecdFieldSet g m objExpr (rfinfo: RecdFieldInfo) argExpr = // Helpers dealing with named and optional args at callsites //------------------------------------------------------------------------- +[] let (|BinOpExpr|_|) expr = match expr with - | SynExpr.App (_, _, SynExpr.App (_, _, SingleIdent opId, a, _), b, _) -> Some (opId, a, b) - | _ -> None + | SynExpr.App (_, _, SynExpr.App (_, _, SingleIdent opId, a, _), b, _) -> ValueSome (opId, a, b) + | _ -> ValueNone +[] let (|SimpleEqualsExpr|_|) expr = match expr with - | BinOpExpr(opId, a, b) when opId.idText = opNameEquals -> Some (a, b) - | _ -> None + | BinOpExpr(opId, a, b) when opId.idText = opNameEquals -> ValueSome (a, b) + | _ -> ValueNone /// Detect a named argument at a callsite let TryGetNamedArg expr = @@ -4120,7 +4122,8 @@ and TcConstraintWhereTyparSupportsMember cenv env newOk tpenv synSupportTys synM let g = cenv.g let traitInfo, tpenv = TcPseudoMemberSpec cenv newOk env synSupportTys tpenv synMemberSig m match traitInfo with - | TTrait(objTys, ".ctor", memberFlags, argTys, returnTy, _) when memberFlags.MemberKind = SynMemberKind.Constructor -> + | TTrait(tys=objTys; memberName=".ctor"; memberFlags=memberFlags; objAndArgTys=argTys; returnTyOpt=returnTy) + when memberFlags.MemberKind = SynMemberKind.Constructor -> match objTys, argTys with | [ty], [] when typeEquiv g ty (GetFSharpViewOfReturnType g returnTy) -> AddCxTypeMustSupportDefaultCtor env.DisplayEnv cenv.css m NoTrace ty @@ -4169,7 +4172,7 @@ and TcPseudoMemberSpec cenv newOk env synTypes tpenv synMemberSig m = let item = Item.OtherName (Some id, memberConstraintTy, None, None, id.idRange) CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, emptyTyparInst, ItemOccurence.Use, env.AccessRights) - TTrait(tys, logicalCompiledName, memberFlags, argTys, returnTy, ref None), tpenv + TTrait(tys, logicalCompiledName, memberFlags, argTys, returnTy, ref None, ref None), tpenv | _ -> error(Error(FSComp.SR.tcInvalidConstraint(), m)) @@ -4508,7 +4511,7 @@ and TcLongIdentType kindOpt (cenv: cenv) newOk checkConstraints occ iwsam env tp let m = synLongId.Range let ad = env.eAccessRights - let tinstEnclosing, tcref = ForceRaise(ResolveTypeLongIdent cenv.tcSink cenv.nameResolver occ OpenQualified env.NameEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No) + let tinstEnclosing, tcref, inst = ForceRaise(ResolveTypeLongIdent cenv.tcSink cenv.nameResolver occ OpenQualified env.NameEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No) CheckIWSAM cenv env checkConstraints iwsam m tcref @@ -4522,7 +4525,7 @@ and TcLongIdentType kindOpt (cenv: cenv) newOk checkConstraints occ iwsam env tp | _, TyparKind.Measure -> TType_measure (Measure.Const tcref), tpenv | _, TyparKind.Type -> - TcTypeApp cenv newOk checkConstraints occ env tpenv m tcref tinstEnclosing [] + TcTypeApp cenv newOk checkConstraints occ env tpenv m tcref tinstEnclosing [] inst /// Some.Long.TypeName /// ty1 SomeLongTypeName @@ -4530,7 +4533,7 @@ and TcLongIdentAppType kindOpt (cenv: cenv) newOk checkConstraints occ iwsam env let (SynLongIdent(tc, _, _)) = longId let ad = env.eAccessRights - let tinstEnclosing, tcref = + let tinstEnclosing, tcref, inst = let tyResInfo = TypeNameResolutionStaticArgsInfo.FromTyArgs args.Length ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.UseInType OpenQualified env.eNameResEnv ad tc tyResInfo PermitDirectReferenceToGeneratedType.No |> ForceRaise @@ -4549,7 +4552,7 @@ and TcLongIdentAppType kindOpt (cenv: cenv) newOk checkConstraints occ iwsam env | _, TyparKind.Type -> if postfix && tcref.Typars m |> List.exists (fun tp -> match tp.Kind with TyparKind.Measure -> true | _ -> false) then error(Error(FSComp.SR.tcInvalidUnitsOfMeasurePrefix(), m)) - TcTypeApp cenv newOk checkConstraints occ env tpenv m tcref tinstEnclosing args + TcTypeApp cenv newOk checkConstraints occ env tpenv m tcref tinstEnclosing args inst | _, TyparKind.Measure -> match args, postfix with @@ -4568,8 +4571,8 @@ and TcNestedAppType (cenv: cenv) newOk checkConstraints occ iwsam env tpenv synL let leftTy, tpenv = TcType cenv newOk checkConstraints occ iwsam env tpenv synLeftTy match leftTy with | AppTy g (tcref, tinst) -> - let tcref = ResolveTypeLongIdentInTyconRef cenv.tcSink cenv.nameResolver env.eNameResEnv (TypeNameResolutionInfo.ResolveToTypeRefs (TypeNameResolutionStaticArgsInfo.FromTyArgs args.Length)) ad m tcref longId - TcTypeApp cenv newOk checkConstraints occ env tpenv m tcref tinst args + let tcref, inst = ResolveTypeLongIdentInTyconRef cenv.tcSink cenv.nameResolver env.eNameResEnv (TypeNameResolutionInfo.ResolveToTypeRefs (TypeNameResolutionStaticArgsInfo.FromTyArgs args.Length)) ad m tcref longId + TcTypeApp cenv newOk checkConstraints occ env tpenv m tcref tinst args inst | _ -> error(Error(FSComp.SR.tcTypeHasNoNestedTypes(), m)) @@ -4994,7 +4997,7 @@ and TcProvidedTypeApp (cenv: cenv) env tpenv tcref args m = /// Note that the generic type may be a nested generic type List.ListEnumerator. /// In this case, 'argsR is only the instantiation of the suffix type arguments, and pathTypeArgs gives /// the prefix of type arguments. -and TcTypeApp (cenv: cenv) newOk checkConstraints occ env tpenv m tcref pathTypeArgs (synArgTys: SynType list) = +and TcTypeApp (cenv: cenv) newOk checkConstraints occ env tpenv m tcref pathTypeArgs (synArgTys: SynType list) (tinst: TypeInst) = let g = cenv.g CheckTyconAccessible cenv.amap m env.AccessRights tcref |> ignore CheckEntityAttributes g tcref m |> CommitOperationResult @@ -5005,16 +5008,22 @@ and TcTypeApp (cenv: cenv) newOk checkConstraints occ env tpenv m tcref pathType if tcref.Deref.IsProvided then TcProvidedTypeApp cenv env tpenv tcref synArgTys m else #endif - let tps, _, tinst, _ = FreshenTyconRef2 g m tcref - - // If we're not checking constraints, i.e. when we first assert the super/interfaces of a type definition, then just - // clear the constraint lists of the freshly generated type variables. A little ugly but fairly localized. - if checkConstraints = NoCheckCxs then tps |> List.iter (fun tp -> tp.SetConstraints []) let synArgTysLength = synArgTys.Length let pathTypeArgsLength = pathTypeArgs.Length if tinst.Length <> pathTypeArgsLength + synArgTysLength then error (TyconBadArgs(env.DisplayEnv, tcref, pathTypeArgsLength + synArgTysLength, m)) + let tps = tinst |> List.skip pathTypeArgsLength |> List.map (fun t -> + match t with + | TType_var(typar, _) + | TType_measure(Measure.Var typar) -> typar + | t -> failwith $"TcTypeApp: {t}" + ) + + // If we're not checking constraints, i.e. when we first assert the super/interfaces of a type definition, then just + // clear the constraint lists of the freshly generated type variables. A little ugly but fairly localized. + if checkConstraints = NoCheckCxs then tps |> List.iter (fun tp -> tp.SetConstraints []) + let argTys, tpenv = // Get the suffix of typars let tpsForArgs = List.skip (tps.Length - synArgTysLength) tps @@ -5060,9 +5069,9 @@ and TcNestedTypeApplication (cenv: cenv) newOk checkConstraints occ iwsam env tp error(Error(FSComp.SR.tcTypeHasNoNestedTypes(), mWholeTypeApp)) match ty with - | TType_app(tcref, _, _) -> + | TType_app(tcref, inst, _) -> CheckIWSAM cenv env checkConstraints iwsam mWholeTypeApp tcref - TcTypeApp cenv newOk checkConstraints occ env tpenv mWholeTypeApp tcref pathTypeArgs tyargs + TcTypeApp cenv newOk checkConstraints occ env tpenv mWholeTypeApp tcref pathTypeArgs tyargs inst | _ -> error(InternalError("TcNestedTypeApplication: expected type application", mWholeTypeApp)) @@ -7064,31 +7073,34 @@ and TcObjectExpr (cenv: cenv) env tpenv (objTy, realObjTy, argopt, binds, extraI TcRecordConstruction cenv objTy true env tpenv None objTy fldsList mWholeExpr else - let item = ForceRaise (ResolveObjectConstructor cenv.nameResolver env.DisplayEnv mObjTy ad objTy) + let ctorCall, baseIdOpt, tpenv = + if isInterfaceTy g objTy then + match argopt with + | None -> + BuildObjCtorCall g mWholeExpr, None, tpenv + | Some _ -> + error(Error(FSComp.SR.tcConstructorForInterfacesDoNotTakeArguments(), mNewExpr)) + else + let item = ForceRaise (ResolveObjectConstructor cenv.nameResolver env.DisplayEnv mObjTy ad objTy) - if isFSharpObjModelTy g objTy && GetCtorShapeCounter env = 1 then - error(Error(FSComp.SR.tcObjectsMustBeInitializedWithObjectExpression(), mNewExpr)) + if isFSharpObjModelTy g objTy && GetCtorShapeCounter env = 1 then + error(Error(FSComp.SR.tcObjectsMustBeInitializedWithObjectExpression(), mNewExpr)) - let ctorCall, baseIdOpt, tpenv = - match item, argopt with - | Item.CtorGroup(methodName, minfos), Some (arg, baseIdOpt) -> - let meths = minfos |> List.map (fun minfo -> minfo, None) - let afterResolution = ForNewConstructors cenv.tcSink env mObjTy methodName minfos - let ad = env.AccessRights - - let expr, tpenv = TcMethodApplicationThen cenv env (MustEqual objTy) None tpenv None [] mWholeExpr mObjTy methodName ad PossiblyMutates false meths afterResolution CtorValUsedAsSuperInit [arg] ExprAtomicFlag.Atomic None [] - // The 'base' value is always bound - let baseIdOpt = (match baseIdOpt with None -> Some(ident("base", mObjTy)) | Some id -> Some id) - expr, baseIdOpt, tpenv - | Item.FakeInterfaceCtor intfTy, None -> - UnifyTypes cenv env mWholeExpr objTy intfTy - let expr = BuildObjCtorCall g mWholeExpr - expr, None, tpenv - | Item.FakeInterfaceCtor _, Some _ -> - error(Error(FSComp.SR.tcConstructorForInterfacesDoNotTakeArguments(), mNewExpr)) - | Item.CtorGroup _, None -> - error(Error(FSComp.SR.tcConstructorRequiresArguments(), mNewExpr)) - | _ -> error(Error(FSComp.SR.tcNewRequiresObjectConstructor(), mNewExpr)) + match item, argopt with + | Item.CtorGroup(methodName, minfos), Some (arg, baseIdOpt) -> + let meths = minfos |> List.map (fun minfo -> minfo, None) + let afterResolution = ForNewConstructors cenv.tcSink env mObjTy methodName minfos + let ad = env.AccessRights + + let expr, tpenv = TcMethodApplicationThen cenv env (MustEqual objTy) None tpenv None [] mWholeExpr mObjTy methodName ad PossiblyMutates false meths afterResolution CtorValUsedAsSuperInit [arg] ExprAtomicFlag.Atomic None [] + // The 'base' value is always bound + let baseIdOpt = (match baseIdOpt with None -> Some(ident("base", mObjTy)) | Some id -> Some id) + expr, baseIdOpt, tpenv + + | Item.CtorGroup _, None -> + error(Error(FSComp.SR.tcConstructorRequiresArguments(), mNewExpr)) + + | _ -> error(Error(FSComp.SR.tcNewRequiresObjectConstructor(), mNewExpr)) let baseValOpt = MakeAndPublishBaseVal cenv env baseIdOpt objTy let env = Option.foldBack (AddLocalVal g cenv.tcSink mNewExpr) baseValOpt env @@ -8194,8 +8206,11 @@ and TcNameOfExpr (cenv: cenv) env tpenv (synArg: SynExpr) = when (match item with | Item.DelegateCtor _ - | Item.CtorGroup _ - | Item.FakeInterfaceCtor _ -> false + | Item.CtorGroup _ -> false + | Item.Types _ when delayed.IsEmpty -> + match delayed with + | [] | [DelayedTypeApp _] -> false + | _ -> true | _ -> true) -> let overallTy = match overallTyOpt with None -> MustEqual (NewInferenceType g) | Some t -> t let _, _ = TcItemThen cenv overallTy env tpenv res None delayed @@ -8209,10 +8224,10 @@ and TcNameOfExpr (cenv: cenv) env tpenv (synArg: SynExpr) = if (match delayed with [DelayedTypeApp _] | [] -> true | _ -> false) then let (TypeNameResolutionInfo(_, staticArgsInfo)) = GetLongIdentTypeNameInfo delayed match ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.UseInAttribute OpenQualified env.eNameResEnv ad longId staticArgsInfo PermitDirectReferenceToGeneratedType.No with - | Result (tinstEnclosing, tcref) when IsEntityAccessible cenv.amap m ad tcref -> + | Result (tinstEnclosing, tcref, inst) when IsEntityAccessible cenv.amap m ad tcref -> match delayed with | [DelayedTypeApp (tyargs, _, mExprAndTypeArgs)] -> - TcTypeApp cenv NewTyparsOK CheckCxs ItemOccurence.UseInType env tpenv mExprAndTypeArgs tcref tinstEnclosing tyargs |> ignore + TcTypeApp cenv NewTyparsOK CheckCxs ItemOccurence.UseInType env tpenv mExprAndTypeArgs tcref tinstEnclosing tyargs inst |> ignore | _ -> () true // resolved to a type name, done with checks | _ -> @@ -8427,9 +8442,6 @@ and TcItemThen (cenv: cenv) (overallTy: OverallTy) env tpenv (tinstEnclosing, it | Item.CtorGroup(nm, minfos) -> TcCtorItemThen cenv overallTy env item nm minfos tinstEnclosing tpenv mItem afterResolution delayed - | Item.FakeInterfaceCtor _ -> - error(Error(FSComp.SR.tcInvalidUseOfInterfaceType(), mItem)) - | Item.ImplicitOp(id, sln) -> TcImplicitOpItemThen cenv overallTy env id sln tpenv mItem delayed @@ -8667,7 +8679,10 @@ and TcTypeItemThen (cenv: cenv) overallTy env nm ty tpenv mItem tinstEnclosing d // In this case the type is not generic, and indeed we should never have returned Item.Types. // That's because ResolveTypeNamesToCtors should have been set at the original // call to ResolveLongIdentAsExprAndComputeRange - error(Error(FSComp.SR.tcInvalidUseOfTypeName(), mItem)) + if isInterfaceTy g ty then + error(Error(FSComp.SR.tcInvalidUseOfInterfaceType(), mItem)) + else + error(Error(FSComp.SR.tcInvalidUseOfTypeName(), mItem)) and TcMethodItemThen (cenv: cenv) overallTy env item methodName minfos tpenv mItem afterResolution staticTyOpt delayed = let ad = env.eAccessRights @@ -8860,7 +8875,7 @@ and TcImplicitOpItemThen (cenv: cenv) overallTy env id sln tpenv mItem delayed = let memberFlags = StaticMemberFlags SynMemberKind.Member let logicalCompiledName = ComputeLogicalName id memberFlags - let traitInfo = TTrait(argTys, logicalCompiledName, memberFlags, argTys, Some retTy, sln) + let traitInfo = TTrait(argTys, logicalCompiledName, memberFlags, argTys, Some retTy, ref None, sln) let expr = Expr.Op (TOp.TraitCall traitInfo, [], ves, mItem) let expr = mkLambdas g mItem [] vs (expr, retTy) @@ -9358,7 +9373,7 @@ and TcLookupItemThen cenv overallTy env tpenv mObjExpr objExpr objExprTy delayed | Item.Trait traitInfo -> TcTraitItemThen cenv overallTy env (Some objExpr) traitInfo tpenv mItem delayed - | Item.FakeInterfaceCtor _ | Item.DelegateCtor _ -> error (Error (FSComp.SR.tcConstructorsCannotBeFirstClassValues(), mItem)) + | Item.DelegateCtor _ -> error (Error (FSComp.SR.tcConstructorsCannotBeFirstClassValues(), mItem)) // These items are not expected here - they can't be the result of a instance member dot-lookup "expr.Ident" | Item.ActivePatternResult _ @@ -10904,7 +10919,7 @@ and TcAttributeEx canFail (cenv: cenv) (env: TcEnv) attrTgt attrEx (synAttr: Syn match ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.UseInAttribute OpenQualified env.eNameResEnv ad tycon TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No with | Exception err -> raze err - | Result(tinstEnclosing, tcref) -> success(TcTypeApp cenv NoNewTypars CheckCxs ItemOccurence.UseInAttribute env tpenv mAttr tcref tinstEnclosing []) + | Result(tinstEnclosing, tcref, inst) -> success(TcTypeApp cenv NoNewTypars CheckCxs ItemOccurence.UseInAttribute env tpenv mAttr tcref tinstEnclosing [] inst) ForceRaise ((try1 (tyid.idText + "Attribute")) |> otherwise (fun () -> (try1 tyid.idText))) diff --git a/src/Compiler/Checking/CheckExpressions.fsi b/src/Compiler/Checking/CheckExpressions.fsi index 16a759c2e3d..852fee213e6 100644 --- a/src/Compiler/Checking/CheckExpressions.fsi +++ b/src/Compiler/Checking/CheckExpressions.fsi @@ -75,7 +75,7 @@ exception UnionPatternsBindDifferentNames of range exception VarBoundTwice of Ident -exception ValueRestriction of DisplayEnv * InfoReader * bool * Val * Typar * range +exception ValueRestriction of DisplayEnv * InfoReader * Val * Typar * range exception ValNotMutable of DisplayEnv * ValRef * range @@ -712,7 +712,8 @@ val TcMatchPattern: synWhenExprOpt: SynExpr option -> Pattern * Expr option * Val list * TcEnv * UnscopedTyparEnv -val (|BinOpExpr|_|): SynExpr -> (Ident * SynExpr * SynExpr) option +[] +val (|BinOpExpr|_|): SynExpr -> (Ident * SynExpr * SynExpr) voption /// Check a set of let bindings in a class or module val TcLetBindings: diff --git a/src/Compiler/Checking/CheckFormatStrings.fs b/src/Compiler/Checking/CheckFormatStrings.fs index e32d073cbd1..ec8b4ae2b91 100644 --- a/src/Compiler/Checking/CheckFormatStrings.fs +++ b/src/Compiler/Checking/CheckFormatStrings.fs @@ -2,6 +2,7 @@ module internal FSharp.Compiler.CheckFormatStrings +open System open System.Text open Internal.Utilities.Library open Internal.Utilities.Library.Extras @@ -58,7 +59,7 @@ let escapeDotnetFormatString str = [] let (|PrefixedBy|_|) (prefix: string) (str: string) = - if str.StartsWith prefix then + if str.StartsWithOrdinal(prefix) then ValueSome prefix.Length else ValueNone @@ -370,12 +371,12 @@ let parseFormatStringInternal // type checker. They should always have '(...)' after for format string. let requireAndSkipInterpolationHoleFormat i = if i < len && fmt[i] = '(' then - let i2 = fmt.IndexOf(")", i+1) + let i2 = fmt.IndexOfOrdinal(")", i+1) if i2 = -1 then failwith (FSComp.SR.forFormatInvalidForInterpolated3()) else let dotnetAlignment = match widthValue with None -> "" | Some w -> "," + (if info.leftJustify then "-" else "") + string w - let dotnetNumberFormat = match fmt[i+1..i2-1] with "" -> "" | s -> ":" + s + let dotnetNumberFormat = match fmt[i+1..i2-1] with s when String.IsNullOrEmpty(s) -> "" | s -> ":" + s appendToDotnetFormatString ("{" + string dotnetFormatStringInterpolationHoleCount + dotnetAlignment + dotnetNumberFormat + "}") dotnetFormatStringInterpolationHoleCount <- dotnetFormatStringInterpolationHoleCount + 1 i2+1 diff --git a/src/Compiler/Checking/CheckIncrementalClasses.fs b/src/Compiler/Checking/CheckIncrementalClasses.fs index 8ef4d3734f9..85262e72a4c 100644 --- a/src/Compiler/Checking/CheckIncrementalClasses.fs +++ b/src/Compiler/Checking/CheckIncrementalClasses.fs @@ -123,7 +123,7 @@ let TcStaticImplicitCtorInfo_Phase2A(cenv: cenv, env, tcref: TyconRef, m, copyOf /// Check and elaborate the "left hand side" of the implicit class construction /// syntax. -let TcImplicitCtorInfo_Phase2A(cenv: cenv, env, tpenv, tcref: TyconRef, vis, attrs, spats, thisIdOpt, baseValOpt: Val option, safeInitInfo, m, copyOfTyconTypars, objTy, thisTy, xmlDoc: PreXmlDoc) = +let TcImplicitCtorInfo_Phase2A(cenv: cenv, env, tpenv, tcref: TyconRef, vis, attrs, pat: SynPat, thisIdOpt, baseValOpt: Val option, safeInitInfo, m, copyOfTyconTypars, objTy, thisTy, xmlDoc: PreXmlDoc) = let g = cenv.g let baseValOpt = @@ -135,16 +135,30 @@ let TcImplicitCtorInfo_Phase2A(cenv: cenv, env, tpenv, tcref: TyconRef, vis, att let env = AddDeclaredTypars CheckForDuplicateTypars copyOfTyconTypars env // Type check arguments by processing them as 'simple' patterns - // NOTE: if we allow richer patterns here this is where we'd process those patterns - let ctorArgNames, patEnv = TcSimplePatsOfUnknownType cenv true CheckCxs env tpenv (SynSimplePats.SimplePats (spats, [], m)) + let ctorArgNames, patEnv, SynSimplePats.SimplePats(spats, _, _) = TcSimplePatsOfUnknownType cenv true CheckCxs env tpenv pat + + let rec reportGeneratedPattern spat = + match spat with + | SynSimplePat.Id(_, _, isCompilerGenerated, _, _, m) -> + if isCompilerGenerated then + errorR (Error(FSComp.SR.parsOnlySimplePatternsAreAllowedInConstructors(), m)) + + | SynSimplePat.Typed(pat, _, _) + | SynSimplePat.Attrib(pat, _, _) -> + reportGeneratedPattern pat + + for spat in spats do + reportGeneratedPattern spat let (TcPatLinearEnv(_, names, _)) = patEnv // Create the values with the given names let _, vspecs = MakeAndPublishSimpleVals cenv env names - if tcref.IsStructOrEnumTycon && isNil spats then + match tcref.IsStructOrEnumTycon, pat with + | true, SynPat.Const(SynConst.Unit, _) -> errorR (ParameterlessStructCtor(tcref.Range)) + | _ -> () // Put them in order let ctorArgs = List.map (fun v -> NameMap.find v vspecs) ctorArgNames diff --git a/src/Compiler/Checking/CheckIncrementalClasses.fsi b/src/Compiler/Checking/CheckIncrementalClasses.fsi index 0de56111ff9..428ae98b632 100644 --- a/src/Compiler/Checking/CheckIncrementalClasses.fsi +++ b/src/Compiler/Checking/CheckIncrementalClasses.fsi @@ -130,7 +130,7 @@ val TcImplicitCtorInfo_Phase2A: tcref: TyconRef * vis: SynAccess option * attrs: SynAttribute list * - spats: SynSimplePat list * + pat: SynPat * thisIdOpt: Ident option * baseValOpt: Val option * safeInitInfo: SafeInitData * diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index 00229e5eb4b..896df82f844 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -171,11 +171,13 @@ and TcSimplePats (cenv: cenv) optionalArgsOK checkConstraints ty env patEnv synS let ps', patEnvR = (patEnv, List.zip ptys ps) ||> List.mapFold (fun patEnv (ty, pat) -> TcSimplePat optionalArgsOK checkConstraints cenv ty env patEnv pat) ps', patEnvR -and TcSimplePatsOfUnknownType (cenv: cenv) optionalArgsOK checkConstraints env tpenv synSimplePats = +and TcSimplePatsOfUnknownType (cenv: cenv) optionalArgsOK checkConstraints env tpenv (pat: SynPat) = let g = cenv.g let argTy = NewInferenceType g let patEnv = TcPatLinearEnv (tpenv, NameMap.empty, Set.empty) - TcSimplePats cenv optionalArgsOK checkConstraints argTy env patEnv synSimplePats + let spats, _ = SimplePatsOfPat cenv.synArgNameGenerator pat + let names, patEnv = TcSimplePats cenv optionalArgsOK checkConstraints argTy env patEnv spats + names, patEnv, spats and TcPatBindingName cenv env id ty isMemberThis vis1 valReprInfo (vFlags: TcPatValFlags) (names, takenNames: Set) = let (TcPatValFlags(inlineFlag, declaredTypars, argAttribs, isMutable, vis2, isCompGen)) = vFlags diff --git a/src/Compiler/Checking/CheckPatterns.fsi b/src/Compiler/Checking/CheckPatterns.fsi index 46e400b8a92..da797b35a88 100644 --- a/src/Compiler/Checking/CheckPatterns.fsi +++ b/src/Compiler/Checking/CheckPatterns.fsi @@ -15,8 +15,8 @@ val TcSimplePatsOfUnknownType: checkConstraints: CheckConstraints -> env: TcEnv -> tpenv: UnscopedTyparEnv -> - synSimplePats: SynSimplePats -> - string list * TcPatLinearEnv + pat: SynPat -> + string list * TcPatLinearEnv * SynSimplePats // Check a pattern, e.g. for a binding or a match clause val TcPat: diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index 9a4ef131363..188e07399c2 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -57,12 +57,12 @@ open FSharp.Compiler.Import open FSharp.Compiler.InfoReader open FSharp.Compiler.Infos open FSharp.Compiler.MethodCalls +open FSharp.Compiler.NameResolution open FSharp.Compiler.Syntax open FSharp.Compiler.Syntax.PrettyNaming open FSharp.Compiler.SyntaxTreeOps open FSharp.Compiler.TcGlobals open FSharp.Compiler.Text -open FSharp.Compiler.Text.Range open FSharp.Compiler.TypedTree open FSharp.Compiler.TypedTreeBasics open FSharp.Compiler.TypedTreeOps @@ -79,7 +79,7 @@ open FSharp.Compiler.TypeProviders // of the constraint resolution carried out by type checking. //------------------------------------------------------------------------- -let compgenId = mkSynId range0 unassignedTyparName +let compgenId = mkSynId Range.range0 unassignedTyparName let NewCompGenTypar (kind, rigid, staticReq, dynamicReq, error) = Construct.NewTypar(kind, rigid, SynTypar(compgenId, staticReq, true), error, dynamicReq, [], false, false) @@ -97,29 +97,10 @@ let NewInferenceMeasurePar () = let NewErrorTypar () = NewCompGenTypar (TyparKind.Type, TyparRigidity.Flexible, TyparStaticReq.None, TyparDynamicReq.No, true) - -let NewErrorMeasureVar () = - NewCompGenTypar (TyparKind.Measure, TyparRigidity.Flexible, TyparStaticReq.None, TyparDynamicReq.No, true) - -let NewInferenceType (g: TcGlobals) = - let tp = Construct.NewTypar (TyparKind.Type, TyparRigidity.Flexible, SynTypar(compgenId, TyparStaticReq.None, true), false, TyparDynamicReq.No, [], false, false) - let nullness = if g.langFeatureNullness then NewNullnessVar() else KnownAmbivalentToNull - TType_var (tp, nullness) let NewErrorType () = mkTyparTy (NewErrorTypar ()) -let NewErrorMeasure () = - Measure.Var (NewErrorMeasureVar ()) - -let NewByRefKindInferenceType (g: TcGlobals) m = - let tp = Construct.NewTypar (TyparKind.Type, TyparRigidity.Flexible, SynTypar(compgenId, TyparStaticReq.HeadType, true), false, TyparDynamicReq.No, [], false, false) - if g.byrefkind_InOut_tcr.CanDeref then - tp.SetConstraints [TyparConstraint.DefaultsTo(10, TType_app(g.byrefkind_InOut_tcr, [], g.knownWithoutNull), m)] - mkTyparTy tp - -let NewInferenceTypes g l = l |> List.map (fun _ -> NewInferenceType g) - let FreshenTypar (g: TcGlobals) rigid (tp: Typar) = let clearStaticReq = g.langVersion.SupportsFeature LanguageFeature.InterfacesWithAbstractStaticMembers let staticReq = if clearStaticReq then TyparStaticReq.None else tp.StaticReq @@ -142,13 +123,6 @@ let FreshenTypeInst g m tpsorig = let FreshMethInst g m fctps tinst tpsorig = FreshenAndFixupTypars g m TyparRigidity.Flexible fctps tinst tpsorig -let FreshenTypars g m tpsorig = - match tpsorig with - | [] -> [] - | _ -> - let _, _, tpTys = FreshenTypeInst g m tpsorig - tpTys - let FreshenMethInfo m (minfo: MethInfo) = let _, _, tpTys = FreshMethInst minfo.TcGlobals m (minfo.GetFormalTyparsOfDeclaringType m) minfo.DeclaringTypeInst minfo.FormalMethodTypars tpTys @@ -1576,7 +1550,7 @@ and SolveDimensionlessNumericType (csenv: ConstraintSolverEnv) ndeep m2 trace ty /// 2. Some additional solutions are forced prior to generalization (permitWeakResolution= Yes or YesDuringCodeGen). See above and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload permitWeakResolution ndeep m2 trace traitInfo : OperationResult = trackErrors { - let (TTrait(supportTys, nm, memFlags, traitObjAndArgTys, retTy, sln)) = traitInfo + let (TTrait(supportTys, nm, memFlags, traitObjAndArgTys, retTy, source, sln)) = traitInfo // Do not re-solve if already solved if sln.Value.IsSome then return true else @@ -1593,8 +1567,8 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload let supportTys = ListSet.setify (typeAEquiv g aenv) supportTys // Rebuild the trait info after removing duplicates - let traitInfo = TTrait(supportTys, nm, memFlags, traitObjAndArgTys, retTy, sln) - let retTy = GetFSharpViewOfReturnType g retTy + let traitInfo = traitInfo.WithSupportTypes supportTys + let retTy = GetFSharpViewOfReturnType g retTy // Assert the object type if the constraint is for an instance member if memFlags.IsInstance then @@ -1895,13 +1869,13 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload None let anonRecdPropSearch = - let isGetProp = nm.StartsWith "get_" + let isGetProp = nm.StartsWithOrdinal("get_") if not isRigid && isGetProp && memFlags.IsInstance then let propName = nm[4..] let props = supportTys |> List.choose (fun ty -> - match NameResolution.TryFindAnonRecdFieldOfType g ty propName with - | Some (NameResolution.Item.AnonRecdField(anonInfo, tinst, i, _)) -> Some (anonInfo, tinst, i) + match TryFindAnonRecdFieldOfType g ty propName with + | Some (Item.AnonRecdField(anonInfo, tinst, i, _)) -> Some (anonInfo, tinst, i) | _ -> None) match props with | [ prop ] -> Some prop @@ -1936,8 +1910,17 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload if List.isSingleton supportTys then FSComp.SR.csTypeDoesNotSupportOperatorNullable(tyString, opName) else FSComp.SR.csTypesDoNotSupportOperatorNullable(tyString, opName) | _ -> - if List.isSingleton supportTys then FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName) - else FSComp.SR.csTypesDoNotSupportOperator(tyString, opName) + match supportTys, source.Value with + | [_], Some s when s.StartsWith("Operators.") -> + let opSource = s[10..] + if opSource = nm then FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName) + else FSComp.SR.csTypeDoesNotSupportOperator(tyString, opSource) + | [_], Some s -> + FSComp.SR.csFunctionDoesNotSupportType(s, tyString, nm) + | [_], _ + -> FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName) + | _, _ + -> FSComp.SR.csTypesDoNotSupportOperator(tyString, opName) return! ErrorD(ConstraintSolverError(err, m, m2)) | _ -> @@ -2114,7 +2097,6 @@ and TransactMemberConstraintSolution traitInfo (trace: OptionalTrace) sln = /// Only consider overload resolution if canonicalizing or all the types are now nominal. /// That is, don't perform resolution if more nominal information may influence the set of available overloads and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) (permitWeakResolution: PermitWeakResolution) nm traitInfo : (TType * MethInfo) list = - let (TTrait(_, _, memFlags, _, _, _)) = traitInfo let results = if permitWeakResolution.Permit || MemberConstraintSupportIsReadyForDeterminingOverloads csenv traitInfo then let m = csenv.m @@ -2124,7 +2106,7 @@ and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) (permitWeakResolutio let minfos = [ for (supportTy, nominalTy) in nominalTys do let infos = - match memFlags.MemberKind with + match traitInfo.MemberFlags.MemberKind with | SynMemberKind.Constructor -> GetIntrinsicConstructorInfosOfType csenv.SolverState.InfoReader m nominalTy | _ -> @@ -2148,8 +2130,7 @@ and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) (permitWeakResolutio // The trait name "op_Explicit" also covers "op_Implicit", so look for that one too. if nm = "op_Explicit" then - let (TTrait(supportTys, _, memFlags, argTys, retTy, soln)) = traitInfo - let traitInfo2 = TTrait(supportTys, "op_Implicit", memFlags, argTys, retTy, soln) + let traitInfo2 = traitInfo.WithMemberName "op_Implicit" results @ GetRelevantMethodsForTrait csenv permitWeakResolution "op_Implicit" traitInfo2 else results @@ -2206,7 +2187,7 @@ and SupportTypeOfMemberConstraintIsSolved (csenv: ConstraintSolverEnv) (traitInf /// Get all the unsolved typars (statically resolved or not) relevant to the member constraint and GetFreeTyparsOfMemberConstraint (csenv: ConstraintSolverEnv) traitInfo = - let (TTrait(supportTys, _, _, argTys, retTy, _)) = traitInfo + let (TTrait(tys=supportTys; objAndArgTys=argTys; returnTyOpt=retTy)) = traitInfo freeInTypesLeftToRightSkippingConstraints csenv.g (supportTys @ argTys @ Option.toList retTy) and MemberConstraintIsReadyForWeakResolution csenv traitInfo = @@ -2290,8 +2271,8 @@ and AddMemberConstraint (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTr and TraitsAreRelated (csenv: ConstraintSolverEnv) retry traitInfo1 traitInfo2 = let g = csenv.g - let (TTrait(tys1, nm1, memFlags1, argTys1, _, _)) = traitInfo1 - let (TTrait(tys2, nm2, memFlags2, argTys2, _, _)) = traitInfo2 + let (TTrait(tys=tys1; memberName=nm1; memberFlags=memFlags1; objAndArgTys=argTys1)) = traitInfo1 + let (TTrait(tys=tys2; memberName=nm2; memberFlags=memFlags2; objAndArgTys=argTys2)) = traitInfo2 memFlags1.IsInstance = memFlags2.IsInstance && nm1 = nm2 && // Multiple op_Explicit and op_Implicit constraints can exist for the same type variable. @@ -2317,8 +2298,8 @@ and EnforceConstraintConsistency (csenv: ConstraintSolverEnv) ndeep m2 trace ret match tpc1, tpc2 with | TyparConstraint.MayResolveMember(traitInfo1, _), TyparConstraint.MayResolveMember(traitInfo2, _) when TraitsAreRelated csenv retry traitInfo1 traitInfo2 -> - let (TTrait(tys1, _, _, argTys1, rty1, _)) = traitInfo1 - let (TTrait(tys2, _, _, argTys2, rty2, _)) = traitInfo2 + let (TTrait(tys=tys1; objAndArgTys=argTys1; returnTyOpt=rty1)) = traitInfo1 + let (TTrait(tys=tys2; objAndArgTys=argTys2; returnTyOpt=rty2)) = traitInfo2 if retry then match tys1, tys2 with | [ty1], [ty2] -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace ty1 ty2 diff --git a/src/Compiler/Checking/ConstraintSolver.fsi b/src/Compiler/Checking/ConstraintSolver.fsi index 990d1b20861..371fa31e598 100644 --- a/src/Compiler/Checking/ConstraintSolver.fsi +++ b/src/Compiler/Checking/ConstraintSolver.fsi @@ -15,61 +15,6 @@ open FSharp.Compiler.Text open FSharp.Compiler.TypedTree open FSharp.Compiler.TypedTreeOps -/// Create a type variable representing the use of a "_" in F# code -val NewAnonTypar: TyparKind * range * TyparRigidity * TyparStaticReq * TyparDynamicReq -> Typar - -/// Create an inference type variable -val NewInferenceType: TcGlobals -> TType - -/// Create an inference type variable for the kind of a byref pointer -val NewByRefKindInferenceType: TcGlobals -> range -> TType - -/// Create an inference type variable representing an error condition when checking an expression -val NewErrorType: unit -> TType - -/// Create an inference type variable representing an error condition when checking a measure -val NewErrorMeasure: unit -> Measure - -/// Create a list of inference type variables, one for each element in the input list -val NewInferenceTypes: TcGlobals -> 'T list -> TType list - -/// Given a set of formal type parameters and their constraints, make new inference type variables for -/// each and ensure that the constraints on the new type variables are adjusted to refer to these. -/// -/// Returns -/// 1. the new type parameters -/// 2. the instantiation mapping old type parameters to inference variables -/// 3. the inference type variables as a list of types. -val FreshenAndFixupTypars: - g: TcGlobals -> - m: range -> - rigid: TyparRigidity -> - Typars -> - TType list -> - Typars -> - Typars * TyparInstantiation * TType list - -/// Given a set of type parameters, make new inference type variables for -/// each and ensure that the constraints on the new type variables are adjusted. -/// -/// Returns -/// 1. the new type parameters -/// 2. the instantiation mapping old type parameters to inference variables -/// 3. the inference type variables as a list of types. -val FreshenTypeInst: g: TcGlobals -> range -> Typars -> Typars * TyparInstantiation * TType list - -/// Given a set of type parameters, make new inference type variables for -/// each and ensure that the constraints on the new type variables are adjusted. -/// -/// Returns the inference type variables as a list of types. -val FreshenTypars: g: TcGlobals -> range -> Typars -> TType list - -/// Given a method, which may be generic, make new inference type variables for -/// its generic parameters, and ensure that the constraints the new type variables are adjusted. -/// -/// Returns the inference type variables as a list of types. -val FreshenMethInfo: range -> MethInfo -> TType list - /// Information about the context of a type equation. [] type ContextInfo = diff --git a/src/Compiler/Checking/FindUnsolved.fs b/src/Compiler/Checking/FindUnsolved.fs index cfc34649ae5..10eb7ab672c 100644 --- a/src/Compiler/Checking/FindUnsolved.fs +++ b/src/Compiler/Checking/FindUnsolved.fs @@ -167,7 +167,7 @@ and accOp cenv env (op, tyargs, args, m) = | _ -> () /// Walk a trait call, collecting type variables -and accTraitInfo cenv env (mFallback : range) (TTrait(tys, _nm, _, argTys, retTy, _sln)) = +and accTraitInfo cenv env (mFallback : range) (TTrait(tys=tys; objAndArgTys=argTys; returnTyOpt=retTy)) = argTys |> accTypeInst cenv env mFallback retTy |> Option.iter (accTy cenv env mFallback) tys |> List.iter (accTy cenv env mFallback) diff --git a/src/Compiler/Checking/InfoReader.fs b/src/Compiler/Checking/InfoReader.fs index c006dc916cf..0028d830b35 100644 --- a/src/Compiler/Checking/InfoReader.fs +++ b/src/Compiler/Checking/InfoReader.fs @@ -4,6 +4,7 @@ /// Select members from a type by name, searching the type hierarchy if needed module internal FSharp.Compiler.InfoReader +open System open System.Collections.Concurrent open System.Collections.Generic open Internal.Utilities.Library @@ -1097,14 +1098,14 @@ let GetXmlDocSigOfEntityRef infoReader m (eref: EntityRef) = else let ccuFileName = libFileOfEntityRef eref let m = eref.Deref - if m.XmlDocSig = "" then + if String.IsNullOrEmpty(m.XmlDocSig) then m.XmlDocSig <- XmlDocSigOfEntity eref Some (ccuFileName, m.XmlDocSig) let GetXmlDocSigOfScopedValRef g (tcref: TyconRef) (vref: ValRef) = let ccuFileName = libFileOfEntityRef tcref let v = vref.Deref - if v.XmlDocSig = "" && v.HasDeclaringEntity then + if String.IsNullOrEmpty(v.XmlDocSig) && v.HasDeclaringEntity then let ap = buildAccessPath vref.DeclaringEntity.CompilationPathOpt let path = if vref.DeclaringEntity.IsModule then @@ -1118,14 +1119,14 @@ let GetXmlDocSigOfScopedValRef g (tcref: TyconRef) (vref: ValRef) = let GetXmlDocSigOfRecdFieldRef (rfref: RecdFieldRef) = let tcref = rfref.TyconRef let ccuFileName = libFileOfEntityRef tcref - if rfref.RecdField.XmlDocSig = "" then + if String.IsNullOrEmpty(rfref.RecdField.XmlDocSig) then rfref.RecdField.XmlDocSig <- XmlDocSigOfProperty [tcref.CompiledRepresentationForNamedType.FullName; rfref.RecdField.LogicalName] Some (ccuFileName, rfref.RecdField.XmlDocSig) let GetXmlDocSigOfUnionCaseRef (ucref: UnionCaseRef) = let tcref = ucref.TyconRef let ccuFileName = libFileOfEntityRef tcref - if ucref.UnionCase.XmlDocSig = "" then + if String.IsNullOrEmpty(ucref.UnionCase.XmlDocSig) then ucref.UnionCase.XmlDocSig <- XmlDocSigOfUnionCase [tcref.CompiledRepresentationForNamedType.FullName; ucref.CaseName] Some (ccuFileName, ucref.UnionCase.XmlDocSig) @@ -1171,7 +1172,7 @@ let GetXmlDocSigOfValRef g (vref: ValRef) = if not vref.IsLocalRef then let ccuFileName = vref.nlr.Ccu.FileName let v = vref.Deref - if v.XmlDocSig = "" && v.HasDeclaringEntity then + if String.IsNullOrEmpty(v.XmlDocSig) && v.HasDeclaringEntity then v.XmlDocSig <- XmlDocSigOfVal g false vref.DeclaringEntity.CompiledRepresentationForNamedType.Name v Some (ccuFileName, v.XmlDocSig) else diff --git a/src/Compiler/Checking/MethodCalls.fs b/src/Compiler/Checking/MethodCalls.fs index 4c1174a8d98..4006f9f0e2a 100644 --- a/src/Compiler/Checking/MethodCalls.fs +++ b/src/Compiler/Checking/MethodCalls.fs @@ -538,7 +538,7 @@ type CalledMeth<'T> // Detect the special case where an indexer setter using param aray takes 'value' argument after ParamArray arguments let isIndexerSetter = match pinfoOpt with - | Some pinfo when pinfo.HasSetter && minfo.LogicalName.StartsWith "set_" && (List.concat fullCurriedCalledArgs).Length >= 2 -> true + | Some pinfo when pinfo.HasSetter && minfo.LogicalName.StartsWithOrdinal("set_") && (List.concat fullCurriedCalledArgs).Length >= 2 -> true | _ -> false let argSetInfos = diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index d8c31361ec4..5abb8569589 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -201,9 +201,6 @@ type Item = /// Represents the resolution of a name to a constructor | CtorGroup of string * MethInfo list - /// Represents the resolution of a name to the fake constructor simulated for an interface type. - | FakeInterfaceCtor of TType - /// Represents the resolution of a name to a delegate | DelegateCtor of TType @@ -276,8 +273,7 @@ type Item = | ValueSome tcref -> tcref.DisplayNameCore | _ -> nm |> DemangleGenericTypeName - | Item.CtorGroup(nm, _) -> nm |> DemangleGenericTypeName - | Item.FakeInterfaceCtor ty + | Item.CtorGroup(nm, _) -> nm |> DemangleGenericTypeName | Item.DelegateCtor ty -> match ty with | AbbrevOrAppTy tcref -> tcref.DisplayNameCore @@ -1570,6 +1566,85 @@ let FreshenUnionCaseRef (ncenv: NameResolver) m (ucref: UnionCaseRef) = let FreshenRecdFieldRef (ncenv: NameResolver) m (rfref: RecdFieldRef) = RecdFieldInfo(ncenv.InstantiationGenerator m (rfref.Tycon.Typars m), rfref) +//------------------------------------------------------------------------- +// Generate type variables and record them in within the scope of the +// compilation environment, which currently corresponds to the scope +// of the constraint resolution carried out by type checking. +//------------------------------------------------------------------------- + +let compgenId = mkSynId range0 unassignedTyparName + +let NewCompGenTypar (kind, rigid, staticReq, dynamicReq, error) = + Construct.NewTypar(kind, rigid, SynTypar(compgenId, staticReq, true), error, dynamicReq, [], false, false) + +let AnonTyparId m = mkSynId m unassignedTyparName + +let NewAnonTypar (kind, m, rigid, var, dyn) = + Construct.NewTypar (kind, rigid, SynTypar(AnonTyparId m, var, true), false, dyn, [], false, false) + +let NewNamedInferenceMeasureVar (_m: range, rigid, var, id) = + Construct.NewTypar(TyparKind.Measure, rigid, SynTypar(id, var, false), false, TyparDynamicReq.No, [], false, false) + +let NewInferenceMeasurePar () = + NewCompGenTypar (TyparKind.Measure, TyparRigidity.Flexible, TyparStaticReq.None, TyparDynamicReq.No, false) + +let NewErrorTypar () = + NewCompGenTypar (TyparKind.Type, TyparRigidity.Flexible, TyparStaticReq.None, TyparDynamicReq.No, true) + +let NewErrorMeasureVar () = + NewCompGenTypar (TyparKind.Measure, TyparRigidity.Flexible, TyparStaticReq.None, TyparDynamicReq.No, true) + +let NewInferenceType (g: TcGlobals) = + ignore g // included for future, minimizing code diffs, see https://github.com/dotnet/fsharp/pull/6804 + mkTyparTy (Construct.NewTypar (TyparKind.Type, TyparRigidity.Flexible, SynTypar(compgenId, TyparStaticReq.None, true), false, TyparDynamicReq.No, [], false, false)) + +let NewErrorType () = + mkTyparTy (NewErrorTypar ()) + +let NewErrorMeasure () = + Measure.Var (NewErrorMeasureVar ()) + +let NewByRefKindInferenceType (g: TcGlobals) m = + let tp = Construct.NewTypar (TyparKind.Type, TyparRigidity.Flexible, SynTypar(compgenId, TyparStaticReq.HeadType, true), false, TyparDynamicReq.No, [], false, false) + if g.byrefkind_InOut_tcr.CanDeref then + tp.SetConstraints [TyparConstraint.DefaultsTo(10, TType_app(g.byrefkind_InOut_tcr, [], g.knownWithoutNull), m)] + mkTyparTy tp + +let NewInferenceTypes g l = l |> List.map (fun _ -> NewInferenceType g) + +let FreshenTypar (g: TcGlobals) rigid (tp: Typar) = + let clearStaticReq = g.langVersion.SupportsFeature LanguageFeature.InterfacesWithAbstractStaticMembers + let staticReq = if clearStaticReq then TyparStaticReq.None else tp.StaticReq + let dynamicReq = if rigid = TyparRigidity.Rigid then TyparDynamicReq.Yes else TyparDynamicReq.No + NewCompGenTypar (tp.Kind, rigid, staticReq, dynamicReq, false) + +// QUERY: should 'rigid' ever really be 'true'? We set this when we know +// we are going to have to generalize a typar, e.g. when implementing a +// abstract generic method slot. But we later check the generalization +// condition anyway, so we could get away with a non-rigid typar. This +// would sort of be cleaner, though give errors later. +let FreshenAndFixupTypars g m rigid fctps tinst tpsorig = + let tps = tpsorig |> List.map (FreshenTypar g rigid) + let renaming, tinst = FixupNewTypars m fctps tinst tpsorig tps + tps, renaming, tinst + +let FreshenTypeInst g m tpsorig = + FreshenAndFixupTypars g m TyparRigidity.Flexible [] [] tpsorig + +let FreshMethInst g m fctps tinst tpsorig = + FreshenAndFixupTypars g m TyparRigidity.Flexible fctps tinst tpsorig + +let FreshenTypars g m tpsorig = + match tpsorig with + | [] -> [] + | _ -> + let _, _, tpTys = FreshenTypeInst g m tpsorig + tpTys + +let FreshenMethInfo m (minfo: MethInfo) = + let _, _, tpTys = FreshMethInst minfo.TcGlobals m (minfo.GetFormalTyparsOfDeclaringType m) minfo.DeclaringTypeInst minfo.FormalMethodTypars + tpTys + /// This must be called after fetching unqualified items that may need to be freshened /// or have type instantiations let ResolveUnqualifiedItem (ncenv: NameResolver) nenv m res = @@ -1713,6 +1788,8 @@ type ItemOccurence = | RelatedText /// This is a usage of a module or namespace name in open statement | Open + /// Not permitted item uses like interface names used as expressions + | InvalidUse type FormatStringCheckContext = { SourceText: ISourceText @@ -1741,88 +1818,100 @@ let (|ValRefOfProp|_|) (pi: PropInfo) = pi.ArbitraryValRef let (|ValRefOfMeth|_|) (mi: MethInfo) = mi.ArbitraryValRef let (|ValRefOfEvent|_|) (evt: EventInfo) = evt.ArbitraryValRef +[] let rec (|RecordFieldUse|_|) (item: Item) = match item with - | Item.RecdField(RecdFieldInfo(_, RecdFieldRef(tcref, name))) -> Some (name, tcref) - | Item.SetterArg(_, RecordFieldUse f) -> Some f - | _ -> None + | Item.RecdField(RecdFieldInfo(_, RecdFieldRef(tcref, name))) -> ValueSome (name, tcref) + | Item.SetterArg(_, RecordFieldUse f) -> ValueSome f + | _ -> ValueNone +[] let (|UnionCaseFieldUse|_|) (item: Item) = match item with - | Item.UnionCaseField (uci, fieldIndex) -> Some (fieldIndex, uci.UnionCaseRef) - | _ -> None + | Item.UnionCaseField (uci, fieldIndex) -> ValueSome (fieldIndex, uci.UnionCaseRef) + | _ -> ValueNone +[] let rec (|ILFieldUse|_|) (item: Item) = match item with - | Item.ILField finfo -> Some finfo - | Item.SetterArg(_, ILFieldUse f) -> Some f - | _ -> None + | Item.ILField finfo -> ValueSome finfo + | Item.SetterArg(_, ILFieldUse f) -> ValueSome f + | _ -> ValueNone +[] let rec (|PropertyUse|_|) (item: Item) = match item with - | Item.Property(info = pinfo :: _) -> Some pinfo - | Item.SetterArg(_, PropertyUse pinfo) -> Some pinfo - | _ -> None + | Item.Property(info = pinfo :: _) -> ValueSome pinfo + | Item.SetterArg(_, PropertyUse pinfo) -> ValueSome pinfo + | _ -> ValueNone +[] let rec (|FSharpPropertyUse|_|) (item: Item) = match item with - | Item.Property(info = [ValRefOfProp vref]) -> Some vref - | Item.SetterArg(_, FSharpPropertyUse propDef) -> Some propDef - | _ -> None + | Item.Property(info = [ValRefOfProp vref]) -> ValueSome vref + | Item.SetterArg(_, FSharpPropertyUse propDef) -> ValueSome propDef + | _ -> ValueNone +[] let (|MethodUse|_|) (item: Item) = match item with - | Item.MethodGroup(_, [minfo], _) -> Some minfo - | _ -> None + | Item.MethodGroup(_, [minfo], _) -> ValueSome minfo + | _ -> ValueNone +[] let (|FSharpMethodUse|_|) (item: Item) = match item with - | Item.MethodGroup(_, [ValRefOfMeth vref], _) -> Some vref - | Item.Value vref when vref.IsMember -> Some vref - | _ -> None + | Item.MethodGroup(_, [ValRefOfMeth vref], _) -> ValueSome vref + | Item.Value vref when vref.IsMember -> ValueSome vref + | _ -> ValueNone +[] let (|EntityUse|_|) (item: Item) = match item with - | Item.UnqualifiedType (tcref :: _) -> Some tcref - | Item.ExnCase tcref -> Some tcref + | Item.UnqualifiedType (tcref :: _) -> ValueSome tcref + | Item.ExnCase tcref -> ValueSome tcref | Item.Types(_, [AbbrevOrAppTy tcref]) - | Item.DelegateCtor(AbbrevOrAppTy tcref) - | Item.FakeInterfaceCtor(AbbrevOrAppTy tcref) -> Some tcref + | Item.DelegateCtor(AbbrevOrAppTy tcref) -> ValueSome tcref | Item.CtorGroup(_, ctor :: _) -> match ctor.ApparentEnclosingType with - | AbbrevOrAppTy tcref -> Some tcref - | _ -> None - | _ -> None + | AbbrevOrAppTy tcref -> ValueSome tcref + | _ -> ValueNone + | _ -> ValueNone +[] let (|EventUse|_|) (item: Item) = match item with - | Item.Event einfo -> Some einfo - | _ -> None + | Item.Event einfo -> ValueSome einfo + | _ -> ValueNone +[] let (|FSharpEventUse|_|) (item: Item) = match item with - | Item.Event(ValRefOfEvent vref) -> Some vref - | _ -> None + | Item.Event(ValRefOfEvent vref) -> ValueSome vref + | _ -> ValueNone +[] let (|UnionCaseUse|_|) (item: Item) = match item with - | Item.UnionCase(UnionCaseInfo(_, u1), _) -> Some u1 - | _ -> None + | Item.UnionCase(UnionCaseInfo(_, u1), _) -> ValueSome u1 + | _ -> ValueNone +[] let (|ValUse|_|) (item: Item) = match item with | Item.Value vref | FSharpPropertyUse vref | FSharpMethodUse vref | FSharpEventUse vref - | Item.CustomBuilder(_, vref) -> Some vref - | _ -> None + | Item.CustomBuilder(_, vref) -> ValueSome vref + | _ -> ValueNone +[] let (|ActivePatternCaseUse|_|) (item: Item) = match item with - | Item.ActivePatternCase(APElemRef(_, vref, idx, _)) -> Some (vref.SigRange, vref.DefinitionRange, idx) - | Item.ActivePatternResult(ap, _, idx, _) -> Some (ap.Range, ap.Range, idx) - | _ -> None + | Item.ActivePatternCase(APElemRef(_, vref, idx, _)) -> ValueSome (vref.SigRange, vref.DefinitionRange, idx) + | Item.ActivePatternResult(ap, _, idx, _) -> ValueSome (ap.Range, ap.Range, idx) + | _ -> ValueNone let tyconRefDefnHash (_g: TcGlobals) (eref1: EntityRef) = hash eref1.LogicalName @@ -2229,7 +2318,6 @@ let CheckAllTyparsInferrable amap m item = | Item.Trait _ | Item.CtorGroup _ - | Item.FakeInterfaceCtor _ | Item.DelegateCtor _ | Item.Types _ | Item.ModuleOrNamespaces _ @@ -2470,7 +2558,8 @@ let private ResolveObjectConstructorPrim (ncenv: NameResolver) edenv resInfo m a else let ctorInfos = GetIntrinsicConstructorInfosOfType ncenv.InfoReader m ty if isNil ctorInfos && isInterfaceTy g ty then - success (resInfo, Item.FakeInterfaceCtor ty) + let tcref = tcrefOfAppTy g ty + success (resInfo, Item.Types(tcref.DisplayName, [ty])) else let defaultStructCtorInfo = if (not (ctorInfos |> List.exists (fun x -> x.IsNullary)) && @@ -2843,9 +2932,10 @@ let private ResolveLongIdentInTyconRefs atMostOne (ncenv: NameResolver) nenv loo // ResolveExprLongIdentInModuleOrNamespace //------------------------------------------------------------------------- +[] let (|AccessibleEntityRef|_|) amap m ad (modref: ModuleOrNamespaceRef) mspec = let eref = modref.NestedTyconRef mspec - if IsEntityAccessible amap m ad eref then Some eref else None + if IsEntityAccessible amap m ad eref then ValueSome eref else ValueNone let rec ResolveExprLongIdentInModuleOrNamespace (ncenv: NameResolver) nenv (typeNameResInfo: TypeNameResolutionInfo) ad resInfo depth m modref (mty: ModuleOrNamespaceType) (id: Ident) (rest: Ident list) = // resInfo records the modules or namespaces actually relevant to a resolution @@ -3070,33 +3160,50 @@ let rec ResolveExprLongIdentPrim sink (ncenv: NameResolver) first fullyQualified match AtMostOneResult m innerSearch with | Result _ as res -> res | _ -> - let failingCase = - match typeError with - | Some e -> raze e - | _ -> - let suggestNamesAndTypes (addToBuffer: string -> unit) = - for e in nenv.eUnqualifiedItems do - if canSuggestThisItem e.Value then - addToBuffer e.Value.DisplayName - - for e in nenv.TyconsByDemangledNameAndArity fullyQualified do - if IsEntityAccessible ncenv.amap m ad e.Value then - addToBuffer e.Value.DisplayName - - for kv in nenv.ModulesAndNamespaces fullyQualified do - for modref in kv.Value do - if IsEntityAccessible ncenv.amap m ad modref then - addToBuffer modref.DisplayName - - // check if the user forgot to use qualified access - for e in nenv.eTyconsByDemangledNameAndArity do - let hasRequireQualifiedAccessAttribute = HasFSharpAttribute ncenv.g ncenv.g.attrib_RequireQualifiedAccessAttribute e.Value.Attribs - if hasRequireQualifiedAccessAttribute then - if e.Value.IsUnionTycon && e.Value.UnionCasesArray |> Array.exists (fun c -> c.LogicalName = id.idText) then - addToBuffer (e.Value.DisplayName + "." + id.idText) - - raze (UndefinedName(0, FSComp.SR.undefinedNameValueOfConstructor, id, suggestNamesAndTypes)) - failingCase + + match typeError with + | Some e -> raze e + | _ -> + + let tyconSearch () = + let tcrefs = LookupTypeNameInEnvNoArity fullyQualified id.idText nenv + if isNil tcrefs then NoResultsOrUsefulErrors else + + let tcrefs = ResolveUnqualifiedTyconRefs nenv tcrefs + let typeNameResInfo = TypeNameResolutionInfo.ResolveToTypeRefs typeNameResInfo.StaticArgsInfo + CheckForTypeLegitimacyAndMultipleGenericTypeAmbiguities (tcrefs, typeNameResInfo, PermitDirectReferenceToGeneratedType.No, unionRanges m id.idRange) + |> CollectResults success + + match tyconSearch () with + | Result((resInfo, tcref) :: _) -> + let _, _, tyargs = FreshenTypeInst ncenv.g m (tcref.Typars m) + let item = Item.Types(id.idText, [TType_app(tcref, tyargs, ncenv.g.knownWithoutNull)]) + success (resInfo, item) + | _ -> + + let suggestNamesAndTypes (addToBuffer: string -> unit) = + for e in nenv.eUnqualifiedItems do + if canSuggestThisItem e.Value then + addToBuffer e.Value.DisplayName + + for e in nenv.TyconsByDemangledNameAndArity fullyQualified do + if IsEntityAccessible ncenv.amap m ad e.Value then + addToBuffer e.Value.DisplayName + + for kv in nenv.ModulesAndNamespaces fullyQualified do + for modref in kv.Value do + if IsEntityAccessible ncenv.amap m ad modref then + addToBuffer modref.DisplayName + + // check if the user forgot to use qualified access + for e in nenv.eTyconsByDemangledNameAndArity do + let hasRequireQualifiedAccessAttribute = HasFSharpAttribute ncenv.g ncenv.g.attrib_RequireQualifiedAccessAttribute e.Value.Attribs + if hasRequireQualifiedAccessAttribute then + if e.Value.IsUnionTycon && e.Value.UnionCasesArray |> Array.exists (fun c -> c.LogicalName = id.idText) then + addToBuffer (e.Value.DisplayName + "." + id.idText) + + raze (UndefinedName(0, FSComp.SR.undefinedNameValueOfConstructor, id, suggestNamesAndTypes)) + match res with | Exception e -> raze e | Result (resInfo, item) -> @@ -3434,9 +3541,12 @@ let ResolveTypeLongIdentInTyconRef sink (ncenv: NameResolver) nenv typeNameResIn | id :: rest -> ForceRaise (ResolveTypeLongIdentInTyconRefPrim ncenv typeNameResInfo ad ResolutionInfo.Empty PermitDirectReferenceToGeneratedType.No 0 m tcref id rest) ResolutionInfo.SendEntityPathToSink(sink, ncenv, nenv, ItemOccurence.Use, ad, resInfo, ResultTyparChecker(fun () -> true)) - let item = Item.Types(tcref.DisplayName, [FreshenTycon ncenv m tcref]) - CallNameResolutionSink sink (rangeOfLid lid, nenv, item, emptyTyparInst, ItemOccurence.UseInType, ad) - tcref + + let _, tinst, tyargs = FreshenTypeInst ncenv.g m (tcref.Typars m) + let item = Item.Types(tcref.DisplayName, [TType_app(tcref, tyargs, ncenv.g.knownWithoutNull)]) + CallNameResolutionSink sink (rangeOfLid lid, nenv, item, tinst, ItemOccurence.UseInType, ad) + + tcref, tyargs /// Create an UndefinedName error with details let SuggestTypeLongIdentInModuleOrNamespace depth (modref: ModuleOrNamespaceRef) amap ad m (id: Ident) = @@ -3580,7 +3690,6 @@ let rec ResolveTypeLongIdentPrim sink (ncenv: NameResolver) occurence first full let r = AddResults searchSoFar (modulSearchFailed()) AtMostOneResult m2 (r |?> (fun tcrefs -> CheckForTypeLegitimacyAndMultipleGenericTypeAmbiguities (tcrefs, typeNameResInfo, genOk, m))) - /// Resolve a long identifier representing a type and report it let ResolveTypeLongIdentAux sink (ncenv: NameResolver) occurence fullyQualified nenv ad (lid: Ident list) staticResInfo genOk = let m = rangeOfLid lid @@ -3595,15 +3704,20 @@ let ResolveTypeLongIdentAux sink (ncenv: NameResolver) occurence fullyQualified match res with | Result (resInfo, tcref) -> ResolutionInfo.SendEntityPathToSink(sink, ncenv, nenv, ItemOccurence.UseInType, ad, resInfo, ResultTyparChecker(fun () -> true)) - let item = Item.Types(tcref.DisplayName, [FreshenTycon ncenv m tcref]) - CallNameResolutionSink sink (m, nenv, item, emptyTyparInst, occurence, ad) - | _ -> () - res + + let _, tinst, tyargs = FreshenTypeInst ncenv.g m (tcref.Typars m) + let item = Item.Types(tcref.DisplayName, [TType_app(tcref, tyargs, ncenv.g.knownWithoutNull)]) + CallNameResolutionSink sink (m, nenv, item, tinst, occurence, ad) + + Result(resInfo, tcref, tyargs) + + | Exception exn -> + Exception exn /// Resolve a long identifier representing a type and report it let ResolveTypeLongIdent sink ncenv occurence fullyQualified nenv ad lid staticResInfo genOk = let res = ResolveTypeLongIdentAux sink ncenv occurence fullyQualified nenv ad lid staticResInfo genOk - (res |?> fun (resInfo, tcref) -> (resInfo.EnclosingTypeInst, tcref)) + res |?> fun (resInfo, tcref, ttypes) -> (resInfo.EnclosingTypeInst, tcref, ttypes) //------------------------------------------------------------------------- // Resolve F#/IL "." syntax in records etc. @@ -3997,6 +4111,11 @@ let NeedsWorkAfterResolution namedItem = | Item.ActivePatternCase apref -> not (List.isEmpty apref.ActivePatternVal.Typars) | _ -> false +let isWrongItemInExpr item = + match item with + | Item.Types _ -> true + | _ -> false + /// Specifies additional work to do after an item has been processed further in type checking. [] type AfterResolution = @@ -4059,17 +4178,23 @@ let ResolveLongIdentAsExprAndComputeRange (sink: TcResultsSink) (ncenv: NameReso | Some _ -> if NeedsWorkAfterResolution item then AfterResolution.RecordResolution(None, (fun tpinst -> callSink(item, tpinst)), callSinkWithSpecificOverload, (fun () -> callSink (item, emptyTyparInst))) + + elif isWrongItemInExpr item then + CallNameResolutionSink sink (itemRange, nenv, item, emptyTyparInst, ItemOccurence.InvalidUse, ad) + AfterResolution.DoNothing + else callSink (item, emptyTyparInst) AfterResolution.DoNothing success (tinstEnclosing, item, itemRange, rest, afterResolution) +[] let (|NonOverridable|_|) namedItem = match namedItem with - | Item.MethodGroup(_, minfos, _) when minfos |> List.exists(fun minfo -> minfo.IsVirtual || minfo.IsAbstract) -> None - | Item.Property(info = pinfos) when pinfos |> List.exists(fun pinfo -> pinfo.IsVirtualProperty) -> None - | _ -> Some () + | Item.MethodGroup(_, minfos, _) when minfos |> List.exists(fun minfo -> minfo.IsVirtual || minfo.IsAbstract) -> ValueNone + | Item.Property(info = pinfos) when pinfos |> List.exists(fun pinfo -> pinfo.IsVirtualProperty) -> ValueNone + | _ -> ValueSome () /// Called for 'expression.Bar' - for VS IntelliSense, we can filter out static members from method groups /// Also called for 'GenericType.Bar' - for VS IntelliSense, we can filter out non-static members from method groups @@ -4500,7 +4625,6 @@ let InfosForTyconConstructors (ncenv: NameResolver) m ad (tcref: TyconRef) = match ResolveObjectConstructor ncenv (DisplayEnv.Empty g) m ad ty with | Result item -> match item with - | Item.FakeInterfaceCtor _ -> None | Item.CtorGroup(nm, ctorInfos) -> let ctors = ctorInfos @@ -5301,7 +5425,6 @@ let rec GetCompletionForItem (ncenv: NameResolver) (nenv: NameResolutionEnv) m a | _ -> () | Item.DelegateCtor _ - | Item.FakeInterfaceCtor _ | Item.CtorGroup _ | Item.UnqualifiedType _ -> for tcref in nenv.TyconsByDemangledNameAndArity(OpenQualified).Values do diff --git a/src/Compiler/Checking/NameResolution.fsi b/src/Compiler/Checking/NameResolution.fsi index 3ba5113b004..c80125f1862 100755 --- a/src/Compiler/Checking/NameResolution.fsi +++ b/src/Compiler/Checking/NameResolution.fsi @@ -94,9 +94,6 @@ type Item = /// Represents the resolution of a name to a constructor | CtorGroup of string * MethInfo list - /// Represents the resolution of a name to the fake constructor simulated for an interface type. - | FakeInterfaceCtor of TType - /// Represents the resolution of a name to a delegate | DelegateCtor of TType @@ -385,6 +382,7 @@ type internal ItemOccurence = | Implemented | RelatedText | Open + | InvalidUse /// Check for equality, up to signature matching val ItemsAreEffectivelyEqual: TcGlobals -> Item -> Item -> bool @@ -678,6 +676,67 @@ exception internal UpperCaseIdentifierInPattern of range /// Generate a new reference to a record field with a fresh type instantiation val FreshenRecdFieldRef: NameResolver -> range -> RecdFieldRef -> RecdFieldInfo +/// Create a type variable representing the use of a "_" in F# code +val NewAnonTypar: TyparKind * range * TyparRigidity * TyparStaticReq * TyparDynamicReq -> Typar + +val NewNamedInferenceMeasureVar: range * TyparRigidity * TyparStaticReq * Ident -> Typar + +val NewNamedInferenceMeasureVar: range * TyparRigidity * TyparStaticReq * Ident -> Typar + +val NewInferenceMeasurePar: unit -> Typar + +/// Create an inference type variable +val NewInferenceType: TcGlobals -> TType + +/// Create an inference type variable for the kind of a byref pointer +val NewByRefKindInferenceType: TcGlobals -> range -> TType + +/// Create an inference type variable representing an error condition when checking an expression +val NewErrorType: unit -> TType + +/// Create an inference type variable representing an error condition when checking a measure +val NewErrorMeasure: unit -> Measure + +/// Create a list of inference type variables, one for each element in the input list +val NewInferenceTypes: TcGlobals -> 'T list -> TType list + +/// Given a set of type parameters, make new inference type variables for +/// each and ensure that the constraints on the new type variables are adjusted. +/// +/// Returns the inference type variables as a list of types. +val FreshenTypars: g: TcGlobals -> range -> Typars -> TType list + +/// Given a method, which may be generic, make new inference type variables for +/// its generic parameters, and ensure that the constraints the new type variables are adjusted. +/// +/// Returns the inference type variables as a list of types. +val FreshenMethInfo: range -> MethInfo -> TType list + +/// Given a set of formal type parameters and their constraints, make new inference type variables for +/// each and ensure that the constraints on the new type variables are adjusted to refer to these. +/// +/// Returns +/// 1. the new type parameters +/// 2. the instantiation mapping old type parameters to inference variables +/// 3. the inference type variables as a list of types. +val FreshenAndFixupTypars: + g: TcGlobals -> + m: range -> + rigid: TyparRigidity -> + fctps: Typars -> + tinst: TType list -> + tpsorig: Typar list -> + Typar list * TyparInstantiation * TTypes + +/// Given a set of type parameters, make new inference type variables for +/// each and ensure that the constraints on the new type variables are adjusted. +/// +/// Returns +/// 1. the new type parameters +/// 2. the instantiation mapping old type parameters to inference variables +/// 3. the inference type variables as a list of types. +val FreshenTypeInst: g: TcGlobals -> m: range -> tpsorig: Typar list -> Typar list * TyparInstantiation * TTypes + /// Resolve a long identifier to a namespace, module. val internal ResolveLongIdentAsModuleOrNamespace: sink: TcResultsSink -> @@ -735,7 +794,7 @@ val internal ResolveTypeLongIdentInTyconRef: m: range -> tcref: TyconRef -> lid: Ident list -> - TyconRef + TyconRef * TypeInst /// Resolve a long identifier to a type definition val internal ResolveTypeLongIdent: @@ -748,7 +807,7 @@ val internal ResolveTypeLongIdent: lid: Ident list -> staticResInfo: TypeNameResolutionStaticArgsInfo -> genOk: PermitDirectReferenceToGeneratedType -> - ResultOrException + ResultOrException /// Resolve a long identifier to a field val internal ResolveField: diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs index 718fcc7610c..ed4126347d2 100644 --- a/src/Compiler/Checking/NicePrint.fs +++ b/src/Compiler/Checking/NicePrint.fs @@ -55,7 +55,7 @@ module internal PrintUtilities = let comment str = wordL (tagText (sprintf "(* %s *)" str)) - let isDiscard (name: string) = name.StartsWith("_") + let isDiscard (name: string) = name.StartsWithOrdinal("_") let ensureFloat (s: string) = if String.forall (fun c -> Char.IsDigit c || c = '-') s then @@ -224,7 +224,7 @@ module internal PrintUtilities = else s) let pathText = trimPathByDisplayEnv denv path - if pathText = "" then tyconTextL else leftL (tagUnknownEntity pathText) ^^ tyconTextL + if String.IsNullOrEmpty(pathText) then tyconTextL else leftL (tagUnknownEntity pathText) ^^ tyconTextL let layoutBuiltinAttribute (denv: DisplayEnv) (attrib: BuiltinAttribInfo) = let tcref = attrib.TyconRef @@ -833,7 +833,7 @@ module PrintTypes = and layoutTraitWithInfo denv env traitInfo = let g = denv.g - let (TTrait(tys, _, memFlags, _, _, _)) = traitInfo + let (TTrait(tys=tys;memberFlags=memFlags)) = traitInfo let nm = traitInfo.MemberDisplayNameCore let nameL = ConvertValLogicalNameToDisplayLayout false (tagMember >> wordL) nm if denv.shortConstraints then @@ -2827,7 +2827,7 @@ let minimalStringsOfTwoTypes denv ty1 ty2 = let denv = denv.SetOpenPaths [] let denv = { denv with includeStaticParametersInTypeNames=true } let makeName t = - let assemblyName = PrintTypes.layoutAssemblyName denv t |> function "" -> "" | name -> sprintf " (%s)" name + let assemblyName = PrintTypes.layoutAssemblyName denv t |> function null | "" -> "" | name -> sprintf " (%s)" name sprintf "%s%s" (stringOfTy denv t) assemblyName (makeName ty1, makeName ty2, stringOfTyparConstraints denv tpcs) diff --git a/src/Compiler/Checking/PatternMatchCompilation.fs b/src/Compiler/Checking/PatternMatchCompilation.fs index 3caacecb982..168bd86e60e 100644 --- a/src/Compiler/Checking/PatternMatchCompilation.fs +++ b/src/Compiler/Checking/PatternMatchCompilation.fs @@ -740,19 +740,22 @@ let ChooseInvestigationPointLeftToRight frontiers = // This is an initial attempt to remove extra typetests/castclass for simple list pattern matching "match x with h :: t -> ... | [] -> ..." // The problem with this technique is that it creates extra locals which inhibit the process of converting pattern matches into linear let bindings. +[] let (|ListConsDiscrim|_|) g = function | (DecisionTreeTest.UnionCase (ucref, tinst)) (* check we can use a simple 'isinst' instruction *) - when tyconRefEq g ucref.TyconRef g.list_tcr_canon & ucref.CaseName = "op_ColonColon" -> Some tinst - | _ -> None + when tyconRefEq g ucref.TyconRef g.list_tcr_canon & ucref.CaseName = "op_ColonColon" -> ValueSome tinst + | _ -> ValueNone +[] let (|ListEmptyDiscrim|_|) g = function | (DecisionTreeTest.UnionCase (ucref, tinst)) (* check we can use a simple 'isinst' instruction *) - when tyconRefEq g ucref.TyconRef g.list_tcr_canon & ucref.CaseName = "op_Nil" -> Some tinst - | _ -> None + when tyconRefEq g ucref.TyconRef g.list_tcr_canon & ucref.CaseName = "op_Nil" -> ValueSome tinst + | _ -> ValueNone #endif +[] let (|ConstNeedsDefaultCase|_|) c = match c with | Const.Decimal _ @@ -767,8 +770,8 @@ let (|ConstNeedsDefaultCase|_|) c = | Const.UInt64 _ | Const.IntPtr _ | Const.UIntPtr _ - | Const.Char _ -> Some () - | _ -> None + | Const.Char _ -> ValueSome () + | _ -> ValueNone /// Build a dtree, equivalent to: TDSwitch("expr", edges, default, m) /// diff --git a/src/Compiler/Checking/PostInferenceChecks.fs b/src/Compiler/Checking/PostInferenceChecks.fs index d92bc67b827..5be7444b85b 100644 --- a/src/Compiler/Checking/PostInferenceChecks.fs +++ b/src/Compiler/Checking/PostInferenceChecks.fs @@ -346,7 +346,7 @@ let rec CheckTypeDeep (cenv: cenv) (visitTy, visitTyconRefOpt, visitAppTyOpt, vi | TType_var (tp, _) when tp.Solution.IsSome -> for cx in tp.Constraints do match cx with - | TyparConstraint.MayResolveMember(TTrait(_, _, _, _, _, soln), _) -> + | TyparConstraint.MayResolveMember(TTrait(solution=soln), _) -> match visitTraitSolutionOpt, soln.Value with | Some visitTraitSolution, Some sln -> visitTraitSolution sln | _ -> () @@ -433,11 +433,11 @@ and CheckTypeConstraintDeep cenv f g env x = | TyparConstraint.IsReferenceType _ | TyparConstraint.RequiresDefaultConstructor _ -> () -and CheckTraitInfoDeep cenv (_, _, _, visitTraitSolutionOpt, _ as f) g env (TTrait(tys, _, _, argTys, retTy, soln)) = - CheckTypesDeep cenv f g env tys - CheckTypesDeep cenv f g env argTys - Option.iter (CheckTypeDeep cenv f g env true ) retTy - match visitTraitSolutionOpt, soln.Value with +and CheckTraitInfoDeep cenv (_, _, _, visitTraitSolutionOpt, _ as f) g env traitInfo = + CheckTypesDeep cenv f g env traitInfo.SupportTypes + CheckTypesDeep cenv f g env traitInfo.CompiledObjectAndArgumentTypes + Option.iter (CheckTypeDeep cenv f g env true ) traitInfo.CompiledReturnType + match visitTraitSolutionOpt, traitInfo.Solution with | Some visitTraitSolution, Some sln -> visitTraitSolution sln | _ -> () diff --git a/src/Compiler/Checking/QuotationTranslator.fs b/src/Compiler/Checking/QuotationTranslator.fs index fa0d317ab95..8173c13755f 100644 --- a/src/Compiler/Checking/QuotationTranslator.fs +++ b/src/Compiler/Checking/QuotationTranslator.fs @@ -167,33 +167,37 @@ exception IgnoringPartOfQuotedTermWarning of string * range let wfail e = raise (InvalidQuotedTerm e) +[] let (|ModuleValueOrMemberUse|_|) g expr = let rec loop expr args = match stripExpr expr with | Expr.App (InnerExprPat(Expr.Val (vref, vFlags, _) as f), fty, tyargs, actualArgs, _m) when vref.IsMemberOrModuleBinding -> - Some(vref, vFlags, f, fty, tyargs, actualArgs @ args) + ValueSome(vref, vFlags, f, fty, tyargs, actualArgs @ args) | Expr.App (f, _fTy, [], actualArgs, _) -> loop f (actualArgs @ args) | Expr.Val (vref, vFlags, _m) as f when (match vref.TryDeclaringEntity with ParentNone -> false | _ -> true) -> let fty = tyOfExpr g f - Some(vref, vFlags, f, fty, [], args) + ValueSome(vref, vFlags, f, fty, [], args) | _ -> - None + ValueNone loop expr [] +[] let (|SimpleArrayLoopUpperBound|_|) expr = match expr with - | Expr.Op (TOp.ILAsm ([AI_sub], _), _, [Expr.Op (TOp.ILAsm ([I_ldlen; AI_conv ILBasicType.DT_I4], _), _, _, _); Expr.Const (Const.Int32 1, _, _) ], _) -> Some () - | _ -> None + | Expr.Op (TOp.ILAsm ([AI_sub], _), _, [Expr.Op (TOp.ILAsm ([I_ldlen; AI_conv ILBasicType.DT_I4], _), _, _, _); Expr.Const (Const.Int32 1, _, _) ], _) -> ValueSome () + | _ -> ValueNone +[] let (|SimpleArrayLoopBody|_|) g expr = match expr with | Expr.Lambda (_, a, b, ([_] as args), DebugPoints (Expr.Let (TBind(forVarLoop, DebugPoints (Expr.Op (TOp.ILAsm ([I_ldelem_any(ILArrayShape [(Some 0, None)], _)], _), [elemTy], [arr; idx], m1), _), seqPoint), body, m2, freeVars), _), m, ty) -> let body = Expr.Let (TBind(forVarLoop, mkCallArrayGet g m1 elemTy arr idx, seqPoint), body, m2, freeVars) let expr = Expr.Lambda (newUnique(), a, b, args, body, m, ty) - Some (arr, elemTy, expr) - | _ -> None + ValueSome (arr, elemTy, expr) + | _ -> ValueNone +[] let (|ObjectInitializationCheck|_|) g expr = // recognize "if this.init@ < 1 then failinit" match expr with @@ -207,8 +211,8 @@ let (|ObjectInitializationCheck|_|) g expr = name.StartsWithOrdinal("init") && selfRef.IsMemberThisVal && valRefEq g failInitRef (ValRefForIntrinsic g.fail_init_info) && - isUnitTy g resultTy -> Some() - | _ -> None + isUnitTy g resultTy -> ValueSome() + | _ -> ValueNone let isSplice g vref = valRefEq g vref g.splice_expr_vref || valRefEq g vref g.splice_raw_expr_vref diff --git a/src/Compiler/Checking/QuotationTranslator.fsi b/src/Compiler/Checking/QuotationTranslator.fsi index 288a8e1e73d..25567f51a63 100644 --- a/src/Compiler/Checking/QuotationTranslator.fsi +++ b/src/Compiler/Checking/QuotationTranslator.fsi @@ -41,10 +41,17 @@ val ConvExprPublic: QuotationGenerationScope -> suppressWitnesses: bool -> Expr val ConvReflectedDefinition: QuotationGenerationScope -> string -> Val -> Expr -> QuotationPickler.MethodBaseData * QuotationPickler.ExprData +[] val (|ModuleValueOrMemberUse|_|): - TcGlobals -> Expr -> (ValRef * ValUseFlag * Expr * TType * TypeInst * Expr list) option + TcGlobals -> Expr -> (ValRef * ValUseFlag * Expr * TType * TypeInst * Expr list) voption + +[] +val (|SimpleArrayLoopUpperBound|_|): Expr -> unit voption + +[] +val (|SimpleArrayLoopBody|_|): TcGlobals -> Expr -> (Expr * TType * Expr) voption + +[] +val (|ObjectInitializationCheck|_|): TcGlobals -> Expr -> unit voption -val (|SimpleArrayLoopUpperBound|_|): Expr -> unit option -val (|SimpleArrayLoopBody|_|): TcGlobals -> Expr -> (Expr * TType * Expr) option -val (|ObjectInitializationCheck|_|): TcGlobals -> Expr -> unit option val isSplice: TcGlobals -> ValRef -> bool diff --git a/src/Compiler/Checking/SignatureHash.fs b/src/Compiler/Checking/SignatureHash.fs index 2e22ca00ce4..077522a7151 100644 --- a/src/Compiler/Checking/SignatureHash.fs +++ b/src/Compiler/Checking/SignatureHash.fs @@ -477,7 +477,7 @@ let calculateHashOfImpliedSignature g observer (expr: ModuleOrNamespaceContents) let rec hashModuleOrNameSpaceBinding (monb: ModuleOrNamespaceBinding) = match monb with - | ModuleOrNamespaceBinding.Binding b when b.Var.LogicalName.StartsWith("doval@") -> 0 + | ModuleOrNamespaceBinding.Binding b when b.Var.LogicalName.StartsWithOrdinal("doval@") -> 0 | ModuleOrNamespaceBinding.Binding b -> HashTastMemberOrVals.hashValOrMemberNoInst (g, observer) (mkLocalValRef b.Var) | ModuleOrNamespaceBinding.Module(moduleInfo, contents) -> hashSingleModuleOrNameSpaceIncludingName (moduleInfo, contents) diff --git a/src/Compiler/Checking/TailCallChecks.fs b/src/Compiler/Checking/TailCallChecks.fs index 1faa9a50a35..cd8dfd2b77c 100644 --- a/src/Compiler/Checking/TailCallChecks.fs +++ b/src/Compiler/Checking/TailCallChecks.fs @@ -18,11 +18,12 @@ open FSharp.Compiler.TypeRelations let PostInferenceChecksStackGuardDepth = GetEnvInteger "FSHARP_TailCallChecks" 50 +[] let (|ValUseAtApp|_|) e = match e with | InnerExprPat(Expr.App(funcExpr = InnerExprPat(Expr.Val(valRef = vref; flags = valUseFlags))) | Expr.Val( - valRef = vref; flags = valUseFlags)) -> Some(vref, valUseFlags) - | _ -> None + valRef = vref; flags = valUseFlags)) -> ValueSome(vref, valUseFlags) + | _ -> ValueNone type TailCallReturnType = | MustReturnVoid // indicates "has unit return type and must return void" @@ -67,8 +68,6 @@ type cenv = amap: Import.ImportMap - reportErrors: bool - /// Values in module that have been marked [] mustTailCall: Zset } @@ -139,12 +138,8 @@ let rec mkArgsForAppliedExpr isBaseCall argsl x = | Expr.Op(TOp.Coerce, _, [ f ], _) -> mkArgsForAppliedExpr isBaseCall argsl f | _ -> [] -/// Check an expression, where the expression is in a position where byrefs can be generated -let rec CheckExprNoByrefs cenv (tailCall: TailCall) expr = - CheckExpr cenv expr PermitByRefExpr.No tailCall - /// Check an expression, warn if it's attributed with TailCall but our analysis concludes it's not a valid tail call -and CheckForNonTailRecCall (cenv: cenv) expr (tailCall: TailCall) = +let CheckForNonTailRecCall (cenv: cenv) expr (tailCall: TailCall) = let g = cenv.g let expr = stripExpr expr let expr = stripDebugPoints expr @@ -152,68 +147,70 @@ and CheckForNonTailRecCall (cenv: cenv) expr (tailCall: TailCall) = match expr with | Expr.App(f, _fty, _tyargs, argsl, m) -> - if cenv.reportErrors then - if cenv.g.langVersion.SupportsFeature LanguageFeature.WarningWhenTailRecAttributeButNonTailRecUsage then - match f with - | ValUseAtApp(vref, valUseFlags) when cenv.mustTailCall.Contains vref.Deref -> - - let canTailCall = - match tailCall with - | TailCall.No -> // an upper level has already decided that this is not in a tailcall position - false - | TailCall.Yes returnType -> - if vref.IsMemberOrModuleBinding && vref.ValReprInfo.IsSome then - let topValInfo = vref.ValReprInfo.Value - - let nowArgs, laterArgs = - let _, curriedArgInfos, _, _ = - GetValReprTypeInFSharpForm cenv.g topValInfo vref.Type m - - if argsl.Length >= curriedArgInfos.Length then - (List.splitAfter curriedArgInfos.Length argsl) - else - ([], argsl) - - let numEnclosingTypars = CountEnclosingTyparsOfActualParentOfVal vref.Deref - - let _, _, _, returnTy, _ = - GetValReprTypeInCompiledForm g topValInfo numEnclosingTypars vref.Type m - - let _, _, isNewObj, isSuperInit, isSelfInit, _, _, _ = - GetMemberCallInfo cenv.g (vref, valUseFlags) - - let isCCall = - match valUseFlags with - | PossibleConstrainedCall _ -> true - | _ -> false - - let hasByrefArg = nowArgs |> List.exists (tyOfExpr cenv.g >> isByrefTy cenv.g) - - let mustGenerateUnitAfterCall = - (Option.isNone returnTy && returnType <> TailCallReturnType.MustReturnVoid) - - let noTailCallBlockers = - not isNewObj - && not isSuperInit - && not isSelfInit - && not mustGenerateUnitAfterCall - && isNil laterArgs - && not (IsValRefIsDllImport cenv.g vref) - && not isCCall - && not hasByrefArg - - noTailCallBlockers // blockers that will prevent the IL level from emmiting a tail instruction + match f with + | ValUseAtApp(vref, valUseFlags) when cenv.mustTailCall.Contains vref.Deref -> + + let canTailCall = + match tailCall with + | TailCall.No -> // an upper level has already decided that this is not in a tailcall position + false + | TailCall.Yes returnType -> + if vref.IsMemberOrModuleBinding && vref.ValReprInfo.IsSome then + let topValInfo = vref.ValReprInfo.Value + + let nowArgs, laterArgs = + let _, curriedArgInfos, _, _ = + GetValReprTypeInFSharpForm cenv.g topValInfo vref.Type m + + if argsl.Length >= curriedArgInfos.Length then + (List.splitAfter curriedArgInfos.Length argsl) else - true + ([], argsl) - // warn if we call inside of recursive scope in non-tail-call manner/with tail blockers. See - // ``Warn successfully in match clause`` - // ``Warn for byref parameters`` - if not canTailCall then - warning (Error(FSComp.SR.chkNotTailRecursive vref.DisplayName, m)) - | _ -> () + let numEnclosingTypars = CountEnclosingTyparsOfActualParentOfVal vref.Deref + + let _, _, _, returnTy, _ = + GetValReprTypeInCompiledForm g topValInfo numEnclosingTypars vref.Type m + + let _, _, isNewObj, isSuperInit, isSelfInit, _, _, _ = + GetMemberCallInfo cenv.g (vref, valUseFlags) + + let isCCall = + match valUseFlags with + | PossibleConstrainedCall _ -> true + | _ -> false + + let hasByrefArg = nowArgs |> List.exists (tyOfExpr cenv.g >> isByrefTy cenv.g) + + let mustGenerateUnitAfterCall = + (Option.isNone returnTy && returnType <> TailCallReturnType.MustReturnVoid) + + let noTailCallBlockers = + not isNewObj + && not isSuperInit + && not isSelfInit + && not mustGenerateUnitAfterCall + && isNil laterArgs + && not (IsValRefIsDllImport cenv.g vref) + && not isCCall + && not hasByrefArg + + noTailCallBlockers // blockers that will prevent the IL level from emmiting a tail instruction + else + true + + // warn if we call inside of recursive scope in non-tail-call manner/with tail blockers. See + // ``Warn successfully in match clause`` + // ``Warn for byref parameters`` + if not canTailCall then + warning (Error(FSComp.SR.chkNotTailRecursive vref.DisplayName, m)) + | _ -> () | _ -> () +/// Check an expression, where the expression is in a position where byrefs can be generated +let rec CheckExprNoByrefs cenv (tailCall: TailCall) expr = + CheckExpr cenv expr PermitByRefExpr.No tailCall + /// Check call arguments, including the return argument. and CheckCall cenv args ctxts (tailCall: TailCall) = // detect CPS-like expressions @@ -729,19 +726,13 @@ and CheckBindings cenv binds = let CheckModuleBinding cenv (isRec: bool) (TBind _ as bind) = // warn for non-rec functions which have the attribute - if - cenv.reportErrors - && cenv.g.langVersion.SupportsFeature LanguageFeature.WarningWhenTailCallAttrOnNonRec - then + if cenv.g.langVersion.SupportsFeature LanguageFeature.WarningWhenTailCallAttrOnNonRec then let isNotAFunction = match bind.Var.ValReprInfo with | Some info -> info.HasNoArgs | _ -> false - if - (not isRec || isNotAFunction) - && HasFSharpAttribute cenv.g cenv.g.attrib_TailCallAttribute bind.Var.Attribs - then + if (not isRec || isNotAFunction) && cenv.g.HasTailCallAttrib bind.Var.Attribs then warning (Error(FSComp.SR.chkTailCallAttrOnNonRec (), bind.Var.Range)) // Check if a let binding to the result of a rec expression is not inside the rec expression @@ -807,7 +798,7 @@ and CheckDefnInModule cenv mdef = let mustTailCall = Seq.fold (fun mustTailCall (v: Val) -> - if HasFSharpAttribute cenv.g cenv.g.attrib_TailCallAttribute v.Attribs then + if cenv.g.HasTailCallAttrib v.Attribs then let newSet = Zset.add v mustTailCall newSet else @@ -844,14 +835,17 @@ and CheckModuleSpec cenv isRec mbind = | ModuleOrNamespaceBinding.Module(_mspec, rhs) -> CheckDefnInModule cenv rhs -let CheckImplFile (g, amap, reportErrors, implFileContents) = - let cenv = - { - g = g - reportErrors = reportErrors - stackGuard = StackGuard(PostInferenceChecksStackGuardDepth, "CheckImplFile") - amap = amap - mustTailCall = Zset.empty valOrder - } - - CheckDefnInModule cenv implFileContents +let CheckImplFile (g: TcGlobals, amap, reportErrors, implFileContents) = + if + reportErrors + && g.langVersion.SupportsFeature LanguageFeature.WarningWhenTailRecAttributeButNonTailRecUsage + then + let cenv = + { + g = g + stackGuard = StackGuard(PostInferenceChecksStackGuardDepth, "CheckImplFile") + amap = amap + mustTailCall = Zset.empty valOrder + } + + CheckDefnInModule cenv implFileContents diff --git a/src/Compiler/Checking/infos.fs b/src/Compiler/Checking/infos.fs index 022a0c6e4c9..5952a87ca98 100644 --- a/src/Compiler/Checking/infos.fs +++ b/src/Compiler/Checking/infos.fs @@ -850,7 +850,7 @@ type MethInfo = member x.IsUnionCaseTester = let tcref = x.ApparentEnclosingTyconRef tcref.IsUnionTycon && - x.LogicalName.StartsWith("get_Is") && + x.LogicalName.StartsWithOrdinal("get_Is") && match x.ArbitraryValRef with | Some v -> v.IsImplied | None -> false @@ -2455,18 +2455,19 @@ let SettersOfPropInfos (pinfos: PropInfo list) = pinfos |> List.choose (fun pinf let GettersOfPropInfos (pinfos: PropInfo list) = pinfos |> List.choose (fun pinfo -> if pinfo.HasGetter then Some(pinfo.GetterMethod, Some pinfo) else None) +[] let (|DifferentGetterAndSetter|_|) (pinfo: PropInfo) = if not (pinfo.HasGetter && pinfo.HasSetter) then - None + ValueNone else match pinfo.GetterMethod.ArbitraryValRef, pinfo.SetterMethod.ArbitraryValRef with | Some getValRef, Some setValRef -> if getValRef.Accessibility <> setValRef.Accessibility then - Some (getValRef, setValRef) + ValueSome (getValRef, setValRef) else match getValRef.ValReprInfo with | Some getValReprInfo when // Getter has an index parameter - getValReprInfo.TotalArgCount > 1 -> Some (getValRef, setValRef) - | _ -> None - | _ -> None \ No newline at end of file + getValReprInfo.TotalArgCount > 1 -> ValueSome (getValRef, setValRef) + | _ -> ValueNone + | _ -> ValueNone \ No newline at end of file diff --git a/src/Compiler/Checking/infos.fsi b/src/Compiler/Checking/infos.fsi index 41998e5253c..406919bfa37 100644 --- a/src/Compiler/Checking/infos.fsi +++ b/src/Compiler/Checking/infos.fsi @@ -1107,4 +1107,5 @@ val SettersOfPropInfos: pinfos: PropInfo list -> (MethInfo * PropInfo option) li val GettersOfPropInfos: pinfos: PropInfo list -> (MethInfo * PropInfo option) list -val (|DifferentGetterAndSetter|_|): pinfo: PropInfo -> (ValRef * ValRef) option +[] +val (|DifferentGetterAndSetter|_|): pinfo: PropInfo -> (ValRef * ValRef) voption diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 6680057750a..30ea98a1a00 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -5,6 +5,7 @@ module internal FSharp.Compiler.IlxGen open FSharp.Compiler.IlxGenSupport +open System open System.IO open System.Reflection open System.Collections.Generic @@ -420,7 +421,7 @@ let CompLocForFixedPath fragName qname (CompPath(sref, cpath)) = let ns = List.map fst ns let ns = textOfPath ns let encl = t |> List.map (fun (s, _) -> s) - let ns = if ns = "" then None else Some ns + let ns = if String.IsNullOrEmpty(ns) then None else Some ns { QualifiedNameOfFile = fragName @@ -2707,7 +2708,7 @@ let CodeGenThen (cenv: cenv) mgbuf (entryPointInfo, methodName, eenv, alreadyUse match selfArgOpt with | Some selfArg when selfArg.LogicalName <> "this" - && not (selfArg.LogicalName.StartsWith("_")) + && not (selfArg.LogicalName.StartsWithOrdinal("_")) && not cenv.options.localOptimizationsEnabled -> let ilTy = selfArg.Type |> GenType cenv m eenv.tyenv @@ -2846,7 +2847,7 @@ and GenExprPreSteps (cenv: cenv) (cgbuf: CodeGenBuffer) eenv expr sequel = match expr with | Expr.Sequential((DebugPointExpr g debugPointName) as dpExpr, codeExpr, NormalSeq, m) -> match cenv.namedDebugPointsForInlinedCode.TryGetValue({ Range = m; Name = debugPointName }) with - | false, _ when debugPointName = "" -> CG.EmitDebugPoint cgbuf m + | false, _ when String.IsNullOrEmpty(debugPointName) -> CG.EmitDebugPoint cgbuf m | false, _ -> // printfn $"---- Unfound debug point {debugPointName} at {m}" // for KeyValue(k,v) in cenv.namedDebugPointsForInlinedCode do @@ -8646,7 +8647,7 @@ and GenMarshal cenv attribs = let safeArrayUserDefinedSubType = // the argument is a System.Type obj, but it's written to MD as a UTF8 string match decoder.FindTypeName "SafeArrayUserDefinedSubType" "" with - | "" -> None + | x when String.IsNullOrEmpty(x) -> None | res -> if (safeArraySubType = ILNativeVariant.IDispatch) diff --git a/src/Compiler/DependencyManager/DependencyProvider.fs b/src/Compiler/DependencyManager/DependencyProvider.fs index adb9ca6ae7c..0fb7be23b6c 100644 --- a/src/Compiler/DependencyManager/DependencyProvider.fs +++ b/src/Compiler/DependencyManager/DependencyProvider.fs @@ -614,7 +614,7 @@ type DependencyProvider let managers = RegisteredDependencyManagers compilerTools (Option.ofString outputDir) reportError - match managers |> Seq.tryFind (fun kv -> path.StartsWith(kv.Value.Key + ":")) with + match managers |> Seq.tryFind (fun kv -> path.StartsWithOrdinal(kv.Value.Key + ":")) with | None -> let err, msg = this.CreatePackageManagerUnknownError(compilerTools, outputDir, path.Split(':').[0], reportError) diff --git a/src/Compiler/DependencyManager/NativeDllResolveHandler.fs b/src/Compiler/DependencyManager/NativeDllResolveHandler.fs index 12aa28c48cc..8a3161a89d8 100644 --- a/src/Compiler/DependencyManager/NativeDllResolveHandler.fs +++ b/src/Compiler/DependencyManager/NativeDllResolveHandler.fs @@ -8,6 +8,7 @@ open System.IO open System.Reflection open System.Runtime.InteropServices open Internal.Utilities +open Internal.Utilities.Library open Internal.Utilities.FSharpEnvironment open FSharp.Compiler.IO @@ -88,7 +89,7 @@ type internal NativeDllResolveHandlerCoreClr(nativeProbingRoots: NativeResolutio let isRooted = Path.IsPathRooted name let useSuffix s = - not (name.Contains(s + ".") || name.EndsWith(s)) // linux devs often append version # to libraries I.e mydll.so.5.3.2 + not (name.Contains(s + ".") || name.EndsWithOrdinal(s)) // linux devs often append version # to libraries I.e mydll.so.5.3.2 let usePrefix = name.IndexOf(Path.DirectorySeparatorChar) = -1 // If name has directory information no add no prefix diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index 6c3868a3081..c5fa370ccb8 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -145,7 +145,7 @@ type Exception with | IntfImplInIntrinsicAugmentation m | OverrideInExtrinsicAugmentation m | IntfImplInExtrinsicAugmentation m - | ValueRestriction(_, _, _, _, _, m) + | ValueRestriction(_, _, _, _, m) | LetRecUnsound(_, _, m) | ObsoleteError(_, m) | ObsoleteWarning(_, m) @@ -591,11 +591,8 @@ module OldStyleMessages = let DeprecatedE () = Message("Deprecated", "%s") let LibraryUseOnlyE () = Message("LibraryUseOnly", "") let MissingFieldsE () = Message("MissingFields", "%s") - let ValueRestriction1E () = Message("ValueRestriction1", "%s%s%s") - let ValueRestriction2E () = Message("ValueRestriction2", "%s%s%s") - let ValueRestriction3E () = Message("ValueRestriction3", "%s") - let ValueRestriction4E () = Message("ValueRestriction4", "%s%s%s") - let ValueRestriction5E () = Message("ValueRestriction5", "%s%s%s") + let ValueRestrictionFunctionE () = Message("ValueRestrictionFunction", "%s%s%s") + let ValueRestrictionE () = Message("ValueRestriction", "%s%s%s") let RecoverableParseErrorE () = Message("RecoverableParseError", "") let ReservedKeywordE () = Message("ReservedKeyword", "%s") let IndentationProblemE () = Message("IndentationProblem", "%s") @@ -960,9 +957,11 @@ type Exception with [ knownReturnType; genericParametersMessage; argsMessage ] |> List.choose id |> String.concat (nl + nl) - |> function - | "" -> nl - | result -> nl + nl + result + nl + nl + |> fun result -> + if String.IsNullOrEmpty(result) then + nl + else + nl + nl + result + nl + nl match failure with | NoOverloadsFound(methodName, overloads, _) -> @@ -1822,7 +1821,7 @@ type Exception with | MissingFields(sl, _) -> os.AppendString(MissingFieldsE().Format(String.concat "," sl + ".")) - | ValueRestriction(denv, infoReader, hasSig, v, _, _) -> + | ValueRestriction(denv, infoReader, v, _, _) -> let denv = { denv with showInferenceTyparAnnotations = true @@ -1830,55 +1829,22 @@ type Exception with let tau = v.TauType - if hasSig then - if isFunTy denv.g tau && (arityOfVal v).HasNoArgs then - let msg = - ValueRestriction1E().Format - v.DisplayName - (NicePrint.stringOfQualifiedValOrMember denv infoReader (mkLocalValRef v)) - v.DisplayName - - os.AppendString msg - else - let msg = - ValueRestriction2E().Format - v.DisplayName - (NicePrint.stringOfQualifiedValOrMember denv infoReader (mkLocalValRef v)) - v.DisplayName + if isFunTy denv.g tau && (arityOfVal v).HasNoArgs then + let msg = + ValueRestrictionFunctionE().Format + v.DisplayName + (NicePrint.stringOfQualifiedValOrMember denv infoReader (mkLocalValRef v)) + v.DisplayName - os.AppendString msg + os.AppendString msg else - match v.MemberInfo with - | Some membInfo when - (match membInfo.MemberFlags.MemberKind with - | SynMemberKind.PropertyGet - | SynMemberKind.PropertySet - | SynMemberKind.Constructor -> true // can't infer extra polymorphism - // can infer extra polymorphism - | _ -> false) - -> - let msg = - ValueRestriction3E() - .Format(NicePrint.stringOfQualifiedValOrMember denv infoReader (mkLocalValRef v)) - - os.AppendString msg - | _ -> - if isFunTy denv.g tau && (arityOfVal v).HasNoArgs then - let msg = - ValueRestriction4E().Format - v.DisplayName - (NicePrint.stringOfQualifiedValOrMember denv infoReader (mkLocalValRef v)) - v.DisplayName - - os.AppendString msg - else - let msg = - ValueRestriction5E().Format - v.DisplayName - (NicePrint.stringOfQualifiedValOrMember denv infoReader (mkLocalValRef v)) - v.DisplayName + let msg = + ValueRestrictionE().Format + v.DisplayName + (NicePrint.stringOfQualifiedValOrMember denv infoReader (mkLocalValRef v)) + v.DisplayName - os.AppendString msg + os.AppendString msg | Parsing.RecoverableParseError -> os.AppendString(RecoverableParseErrorE().Format) diff --git a/src/Compiler/Driver/CompilerImports.fs b/src/Compiler/Driver/CompilerImports.fs index 8b106683b29..4421ed299ed 100644 --- a/src/Compiler/Driver/CompilerImports.fs +++ b/src/Compiler/Driver/CompilerImports.fs @@ -490,6 +490,26 @@ let IsExe fileName = let ext = Path.GetExtension fileName String.Compare(ext, ".exe", StringComparison.OrdinalIgnoreCase) = 0 +let addConstraintSources(ia: ImportedAssembly) = + let contents = ia.FSharpViewOfMetadata.Contents + let addCxsToMember name (v: Val) = + for typar in fst v.GeneralizedType do + for cx in typar.Constraints do + match cx with + | TyparConstraint.MayResolveMember(TTrait(source=source), _) -> + source.Value <- Some name + | _ -> () + let rec addCxsToModule name (m: ModuleOrNamespaceType) = + for e in m.ModuleAndNamespaceDefinitions do + if e.IsModuleOrNamespace then + let mname = + if String.length name > 0 then name + "." + e.DisplayName + elif e.IsModule then e.DisplayName + else "" + addCxsToModule mname e.ModuleOrNamespaceType + for memb in m.AllValsAndMembers do addCxsToMember (name + "." + memb.LogicalName) memb + addCxsToModule "" contents.ModuleOrNamespaceType + type TcConfig with member tcConfig.TryResolveLibWithDirectories(r: AssemblyReference) = @@ -2327,6 +2347,9 @@ and [] TcImports let _dllinfos, phase2s = results |> Array.choose id |> List.ofArray |> List.unzip fixupOrphanCcus () let ccuinfos = List.collect (fun phase2 -> phase2 ()) phase2s + if importsBase.IsSome then + importsBase.Value.CcuTable.Values |> Seq.iter addConstraintSources + ccuTable.Values |> Seq.iter addConstraintSources return ccuinfos } diff --git a/src/Compiler/Driver/CompilerOptions.fs b/src/Compiler/Driver/CompilerOptions.fs index 04c766d8b9f..b85cf795f0e 100644 --- a/src/Compiler/Driver/CompilerOptions.fs +++ b/src/Compiler/Driver/CompilerOptions.fs @@ -109,7 +109,7 @@ let compilerOptionUsage (CompilerOption(s, tag, spec, _, _)) = | OptionFloat _ -> sprintf "--%s:%s" s tag | OptionRest _ -> sprintf "--%s ..." s | OptionGeneral _ -> - if tag = "" then + if String.IsNullOrEmpty(tag) then sprintf "%s" s else sprintf "%s:%s" s tag (* still being decided *) @@ -270,7 +270,7 @@ let ParseCompilerOptions (collectOtherArgument: string -> unit, blocks: Compiler let optArgs = String.Join(":", opts[1..]) let opt = - if option = "" then + if String.IsNullOrEmpty(option) then "" // if it doesn't start with a '-' or '/', reject outright elif option[0] <> '-' && option[0] <> '/' then @@ -298,13 +298,13 @@ let ParseCompilerOptions (collectOtherArgument: string -> unit, blocks: Compiler opt, token, optArgs let getOptionArg compilerOption (argString: string) = - if argString = "" then + if String.IsNullOrEmpty(argString) then errorR (Error(FSComp.SR.buildOptionRequiresParameter (compilerOptionUsage compilerOption), rangeCmdArgs)) argString let getOptionArgList compilerOption (argString: string) = - if argString = "" then + if String.IsNullOrEmpty(argString) then errorR (Error(FSComp.SR.buildOptionRequiresParameter (compilerOptionUsage compilerOption), rangeCmdArgs)) [] else @@ -375,19 +375,19 @@ let ParseCompilerOptions (collectOtherArgument: string -> unit, blocks: Compiler reportDeprecatedOption d f blocks t - | CompilerOption(s, _, OptionUnit f, d, _) :: _ when optToken = s && argString = "" -> + | CompilerOption(s, _, OptionUnit f, d, _) :: _ when optToken = s && String.IsNullOrEmpty(argString) -> reportDeprecatedOption d f () t - | CompilerOption(s, _, OptionSwitch f, d, _) :: _ when getSwitchOpt optToken = s && argString = "" -> + | CompilerOption(s, _, OptionSwitch f, d, _) :: _ when getSwitchOpt optToken = s && String.IsNullOrEmpty(argString) -> reportDeprecatedOption d f (getSwitch opt) t - | CompilerOption(s, _, OptionSet f, d, _) :: _ when optToken = s && argString = "" -> + | CompilerOption(s, _, OptionSet f, d, _) :: _ when optToken = s && String.IsNullOrEmpty(argString) -> reportDeprecatedOption d f.Value <- true t - | CompilerOption(s, _, OptionClear f, d, _) :: _ when optToken = s && argString = "" -> + | CompilerOption(s, _, OptionClear f, d, _) :: _ when optToken = s && String.IsNullOrEmpty(argString) -> reportDeprecatedOption d f.Value <- false t diff --git a/src/Compiler/Driver/CreateILModule.fs b/src/Compiler/Driver/CreateILModule.fs index 7fa60a25957..04cda7f6c3f 100644 --- a/src/Compiler/Driver/CreateILModule.fs +++ b/src/Compiler/Driver/CreateILModule.fs @@ -409,7 +409,7 @@ module MainModuleBuilder = yield! codegenResults.ilAssemAttrs if Option.isSome pdbfile then - tcGlobals.mkDebuggableAttributeV2 (tcConfig.jitTracking, disableJitOptimizations, false (* enableEnC *) ) + tcGlobals.mkDebuggableAttributeV2 (tcConfig.jitTracking, disableJitOptimizations) yield! reflectedDefinitionAttrs ] @@ -584,19 +584,22 @@ module MainModuleBuilder = [ resource ] // a user cannot specify both win32res and win32manifest - if not (tcConfig.win32manifest = "") && not (tcConfig.win32res = "") then + if + not (String.IsNullOrEmpty(tcConfig.win32manifest)) + && not (String.IsNullOrEmpty(tcConfig.win32res)) + then error (Error(FSComp.SR.fscTwoResourceManifests (), rangeCmdArgs)) let win32Manifest = // use custom manifest if provided - if not (tcConfig.win32manifest = "") then + if not (String.IsNullOrEmpty(tcConfig.win32manifest)) then tcConfig.win32manifest // don't embed a manifest if target is not an exe, if manifest is specifically excluded, if another native resource is being included, or if running on mono elif not (tcConfig.target.IsExe) || not (tcConfig.includewin32manifest) - || not (tcConfig.win32res = "") + || not (String.IsNullOrEmpty(tcConfig.win32res)) then "" // otherwise, include the default manifest @@ -618,9 +621,9 @@ module MainModuleBuilder = [ for av in assemblyVersionResources assemblyVersion do ILNativeResource.Out av - if not (tcConfig.win32res = "") then + if not (String.IsNullOrEmpty(tcConfig.win32res)) then ILNativeResource.Out(FileSystem.OpenFileForReadShim(tcConfig.win32res).ReadAllBytes()) - if tcConfig.includewin32manifest && not (win32Manifest = "") then + if tcConfig.includewin32manifest && not (String.IsNullOrEmpty(win32Manifest)) then ILNativeResource.Out [| yield! ResFileFormat.ResFileHeader() @@ -631,8 +634,8 @@ module MainModuleBuilder = )) |] if - tcConfig.win32res = "" - && tcConfig.win32icon <> "" + String.IsNullOrEmpty(tcConfig.win32res) + && not (String.IsNullOrEmpty(tcConfig.win32icon)) && tcConfig.target <> CompilerTarget.Dll then use ms = new MemoryStream() diff --git a/src/Compiler/Driver/FxResolver.fs b/src/Compiler/Driver/FxResolver.fs index 6f8643c30a1..42681600f88 100644 --- a/src/Compiler/Driver/FxResolver.fs +++ b/src/Compiler/Driver/FxResolver.fs @@ -238,7 +238,7 @@ type internal FxResolver dotnetConfig.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) + pattern.Length - let endPos = dotnetConfig.IndexOf("\"", startPos) + let endPos = dotnetConfig.IndexOfOrdinal("\"", startPos) let ver = dotnetConfig[startPos .. endPos - 1] let path = @@ -364,7 +364,7 @@ type internal FxResolver let implDir, warnings = getImplementationAssemblyDir () let version = DirectoryInfo(implDir).Name - if version.StartsWith("x") then + if version.StartsWithOrdinal("x") then // Is running on the desktop (None, None), warnings else @@ -403,7 +403,7 @@ type internal FxResolver | ".NET", "Core" when arr.Length >= 3 -> Some("netcoreapp" + (getTfmNumber arr[2])) | ".NET", "Framework" when arr.Length >= 3 -> - if arr[2].StartsWith("4.8") then + if arr[2].StartsWithOrdinal("4.8") then Some "net48" else Some "net472" @@ -560,7 +560,7 @@ type internal FxResolver dotnetConfig.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) + pattern.Length - let endPos = dotnetConfig.IndexOf("\"", startPos) + let endPos = dotnetConfig.IndexOfOrdinal("\"", startPos) let tfm = dotnetConfig[startPos .. endPos - 1] tfm with _ -> diff --git a/src/Compiler/Driver/GraphChecking/DependencyResolution.fs b/src/Compiler/Driver/GraphChecking/DependencyResolution.fs index 9300385b483..11ba984ca51 100644 --- a/src/Compiler/Driver/GraphChecking/DependencyResolution.fs +++ b/src/Compiler/Driver/GraphChecking/DependencyResolution.fs @@ -1,7 +1,6 @@ module internal FSharp.Compiler.GraphChecking.DependencyResolution open FSharp.Compiler.Syntax -open Internal.Utilities.Library /// Find a path from a starting TrieNode and return the end node or None let queryTriePartial (trie: TrieNode) (path: LongIdentifier) : TrieNode option = @@ -118,6 +117,20 @@ let rec processStateEntry (trie: TrieNode) (state: FileContentQueryState) (entry FoundDependencies = foundDependencies } + | ModuleName name -> + // We need to check if the module name is a hit in the Trie. + let state' = + let queryResult = queryTrie trie [ name ] + processIdentifier queryResult state + + match state.OwnNamespace with + | None -> state' + | Some ns -> + // If there we currently have our own namespace, + // the combination of that namespace + module name should be checked as well. + let queryResult = queryTrieDual trie ns [ name ] + processIdentifier queryResult state' + /// /// For a given file's content, collect all missing ("ghost") file dependencies that the core resolution algorithm didn't return, /// but are required to satisfy the type-checker. diff --git a/src/Compiler/Driver/GraphChecking/FileContentMapping.fs b/src/Compiler/Driver/GraphChecking/FileContentMapping.fs index 8ece68bd4bb..a460779e51d 100644 --- a/src/Compiler/Driver/GraphChecking/FileContentMapping.fs +++ b/src/Compiler/Driver/GraphChecking/FileContentMapping.fs @@ -18,6 +18,11 @@ let longIdentToPath (skipLast: bool) (longId: LongIdent) : LongIdentifier = let synLongIdentToPath (skipLast: bool) (synLongIdent: SynLongIdent) = longIdentToPath skipLast synLongIdent.LongIdent +/// In some rare cases we are interested in the name of a single Ident. +/// For example `nameof ModuleName` in expressions or patterns. +let visitIdentAsPotentialModuleName (moduleNameIdent: Ident) = + FileContentEntry.ModuleName moduleNameIdent.idText + let visitSynLongIdent (lid: SynLongIdent) : FileContentEntry list = visitLongIdent lid.LongIdent let visitLongIdent (lid: LongIdent) = @@ -200,7 +205,7 @@ let visitSynMemberDefn (md: SynMemberDefn) : FileContentEntry list = | SynMemberDefn.GetSetMember(memberDefnForGet, memberDefnForSet, _, _) -> yield! collectFromOption visitBinding memberDefnForGet yield! collectFromOption visitBinding memberDefnForSet - | SynMemberDefn.ImplicitCtor(ctorArgs = ctorArgs) -> yield! visitSynSimplePats ctorArgs + | SynMemberDefn.ImplicitCtor(ctorArgs = pat) -> yield! visitPat pat | SynMemberDefn.ImplicitInherit(inheritType, inheritArgs, _, _) -> yield! visitSynType inheritType yield! visitSynExpr inheritArgs @@ -305,9 +310,28 @@ let visitSynTypeConstraint (tc: SynTypeConstraint) : FileContentEntry list = | SynTypeConstraint.WhereTyparIsEnum(typeArgs = typeArgs) -> List.collect visitSynType typeArgs | SynTypeConstraint.WhereTyparIsDelegate(typeArgs = typeArgs) -> List.collect visitSynType typeArgs +[] +let inline (|NameofIdent|_|) (ident: Ident) = + if ident.idText = "nameof" then ValueSome() else ValueNone + +/// Special case of `nameof Module` type of expression +let (|NameofExpr|_|) (e: SynExpr) = + let rec stripParen (e: SynExpr) = + match e with + | SynExpr.Paren(expr = expr) -> stripParen expr + | _ -> e + + match e with + | SynExpr.App(flag = ExprAtomicFlag.NonAtomic; isInfix = false; funcExpr = SynExpr.Ident NameofIdent; argExpr = moduleNameExpr) -> + match stripParen moduleNameExpr with + | SynExpr.Ident moduleNameIdent -> Some moduleNameIdent + | _ -> None + | _ -> None + let visitSynExpr (e: SynExpr) : FileContentEntry list = let rec visit (e: SynExpr) (continuation: FileContentEntry list -> FileContentEntry list) : FileContentEntry list = match e with + | NameofExpr moduleNameIdent -> continuation [ visitIdentAsPotentialModuleName moduleNameIdent ] | SynExpr.Const _ -> continuation [] | SynExpr.Paren(expr = expr) -> visit expr continuation | SynExpr.Quote(operator = operator; quotedExpr = quotedExpr) -> @@ -392,7 +416,7 @@ let visitSynExpr (e: SynExpr) : FileContentEntry list = | SynExpr.IfThenElse(ifExpr = ifExpr; thenExpr = thenExpr; elseExpr = elseExpr) -> let continuations = List.map visit (ifExpr :: thenExpr :: Option.toList elseExpr) Continuation.concatenate continuations continuation - | SynExpr.Typar _ -> continuation [] + | SynExpr.Typar _ | SynExpr.Ident _ -> continuation [] | SynExpr.LongIdent(longDotId = longDotId) -> continuation (visitSynLongIdent longDotId) | SynExpr.LongIdentSet(longDotId, expr, _) -> visit expr (fun nodes -> visitSynLongIdent longDotId @ nodes |> continuation) @@ -520,9 +544,29 @@ let visitSynExpr (e: SynExpr) : FileContentEntry list = visit e id +/// Special case of `| nameof Module ->` type of pattern +let (|NameofPat|_|) (pat: SynPat) = + let rec stripPats p = + match p with + | SynPat.Paren(pat = pat) -> stripPats pat + | _ -> p + + match pat with + | SynPat.LongIdent(longDotId = SynLongIdent(id = [ NameofIdent ]); typarDecls = None; argPats = SynArgPats.Pats [ moduleNamePat ]) -> + match stripPats moduleNamePat with + | SynPat.LongIdent( + longDotId = SynLongIdent.SynLongIdent(id = [ moduleNameIdent ]; dotRanges = []; trivia = [ None ]) + extraId = None + typarDecls = None + argPats = SynArgPats.Pats [] + accessibility = None) -> Some moduleNameIdent + | _ -> None + | _ -> None + let visitPat (p: SynPat) : FileContentEntry list = let rec visit (p: SynPat) (continuation: FileContentEntry list -> FileContentEntry list) : FileContentEntry list = match p with + | NameofPat moduleNameIdent -> continuation [ visitIdentAsPotentialModuleName moduleNameIdent ] | SynPat.Paren(pat = pat) -> visit pat continuation | SynPat.Typed(pat = pat; targetType = t) -> visit pat (fun nodes -> nodes @ visitSynType t) | SynPat.Const _ -> continuation [] diff --git a/src/Compiler/Driver/GraphChecking/Graph.fs b/src/Compiler/Driver/GraphChecking/Graph.fs index dd51ea190a2..dbe4c6b6cc7 100644 --- a/src/Compiler/Driver/GraphChecking/Graph.fs +++ b/src/Compiler/Driver/GraphChecking/Graph.fs @@ -27,26 +27,43 @@ module internal Graph = |> Array.map (fun (KeyValue(k, v)) -> k, v) |> readOnlyDict - let transitive<'Node when 'Node: equality> (graph: Graph<'Node>) : Graph<'Node> = - /// Find transitive dependencies of a single node. - let transitiveDeps (node: 'Node) = - let visited = HashSet<'Node>() + let nodes (graph: Graph<'Node>) : Set<'Node> = + graph.Values |> Seq.collect id |> Seq.append graph.Keys |> Set + + /// Find transitive dependencies of a single node. + let transitiveDeps (node: 'Node) (graph: Graph<'Node>) = + let visited = HashSet<'Node>() - let rec dfs (node: 'Node) = - graph[node] - // Add direct dependencies. - // Use HashSet.Add return value semantics to filter out those that were added previously. - |> Array.filter visited.Add - |> Array.iter dfs + let rec dfs (node: 'Node) = + graph[node] + // Add direct dependencies. + // Use HashSet.Add return value semantics to filter out those that were added previously. + |> Array.filter visited.Add + |> Array.iter dfs - dfs node - visited |> Seq.toArray + dfs node + visited |> Seq.toArray + let transitive<'Node when 'Node: equality> (graph: Graph<'Node>) : Graph<'Node> = graph.Keys |> Seq.toArray - |> Array.Parallel.map (fun node -> node, transitiveDeps node) + |> Array.Parallel.map (fun node -> node, graph |> transitiveDeps node) |> readOnlyDict + // TODO: optimize + /// Get subgraph of the given graph that contains only nodes that are reachable from the given node. + let subGraphFor node graph = + let allDeps = graph |> transitiveDeps node + let relevant n = n = node || allDeps |> Array.contains n + + graph + |> Seq.choose (fun (KeyValue(src, deps)) -> + if relevant src then + Some(src, deps |> Array.filter relevant) + else + None) + |> make + /// Create a reverse of the graph let reverse (originalGraph: Graph<'Node>) : Graph<'Node> = originalGraph @@ -69,7 +86,7 @@ module internal Graph = let print (graph: Graph<'Node>) : unit = printCustom graph (fun node -> node.ToString()) - let serialiseToMermaid path (graph: Graph) = + let serialiseToMermaid (graph: Graph) = let sb = StringBuilder() let appendLine (line: string) = sb.AppendLine(line) |> ignore @@ -84,8 +101,10 @@ module internal Graph = appendLine $" %i{idx} --> %i{depIdx}" appendLine "```" + sb.ToString() + let writeMermaidToFile path (graph: Graph) = use out = FileSystem.OpenFileForWriteShim(path, fileMode = System.IO.FileMode.Create) - out.WriteAllText(sb.ToString()) + graph |> serialiseToMermaid |> out.WriteAllText diff --git a/src/Compiler/Driver/GraphChecking/Graph.fsi b/src/Compiler/Driver/GraphChecking/Graph.fsi index 95542470d8a..a93e429d2fe 100644 --- a/src/Compiler/Driver/GraphChecking/Graph.fsi +++ b/src/Compiler/Driver/GraphChecking/Graph.fsi @@ -10,12 +10,18 @@ module internal Graph = /// Build the graph. val make: nodeDeps: seq<'Node * 'Node array> -> Graph<'Node> when 'Node: equality val map<'T, 'U when 'U: equality> : f: ('T -> 'U) -> graph: Graph<'T> -> Graph<'U> + /// Get all nodes of the graph. + val nodes: graph: Graph<'Node> -> Set<'Node> /// Create a transitive closure of the graph in O(n^2) time (but parallelize it). /// The resulting graph contains edge A -> C iff the input graph contains a (directed) non-zero length path from A to C. val transitive<'Node when 'Node: equality> : graph: Graph<'Node> -> Graph<'Node> + /// Get a sub-graph of the graph containing only the nodes reachable from the given node. + val subGraphFor: node: 'Node -> graph: Graph<'Node> -> Graph<'Node> when 'Node: equality /// Create a reverse of the graph. val reverse<'Node when 'Node: equality> : originalGraph: Graph<'Node> -> Graph<'Node> /// Print the contents of the graph to the standard output. val print: graph: Graph<'Node> -> unit + /// Create a simple Mermaid graph + val serialiseToMermaid: graph: Graph -> string /// Create a simple Mermaid graph and save it under the path specified. - val serialiseToMermaid: path: string -> graph: Graph -> unit + val writeMermaidToFile: path: string -> graph: Graph -> unit diff --git a/src/Compiler/Driver/GraphChecking/GraphProcessing.fs b/src/Compiler/Driver/GraphChecking/GraphProcessing.fs index 47993e00862..afe491b4b74 100644 --- a/src/Compiler/Driver/GraphChecking/GraphProcessing.fs +++ b/src/Compiler/Driver/GraphChecking/GraphProcessing.fs @@ -1,6 +1,9 @@ module internal FSharp.Compiler.GraphChecking.GraphProcessing open System.Threading +open FSharp.Compiler.GraphChecking +open System.Threading.Tasks +open System /// Information about the node in a graph, describing its relation with other nodes. type NodeInfo<'Item> = @@ -32,6 +35,9 @@ type ProcessedNode<'Item, 'Result> = Result: 'Result } +type GraphProcessingException(msg, ex: System.Exception) = + inherit exn(msg, ex) + let processGraph<'Item, 'Result when 'Item: equality and 'Item: comparison> (graph: Graph<'Item>) (work: ('Item -> ProcessedNode<'Item, 'Result>) -> NodeInfo<'Item> -> 'Result) @@ -150,7 +156,7 @@ let processGraph<'Item, 'Result when 'Item: equality and 'Item: comparison> // If we stopped early due to an exception, reraise it. match getExn () with | None -> () - | Some(item, ex) -> raise (System.Exception($"Encountered exception when processing item '{item}'", ex)) + | Some(item, ex) -> raise (GraphProcessingException($"Encountered exception when processing item '{item}'", ex)) // All calculations succeeded - extract the results and sort in input order. nodes.Values @@ -162,3 +168,131 @@ let processGraph<'Item, 'Result when 'Item: equality and 'Item: comparison> node.Info.Item, result) |> Seq.sortBy fst |> Seq.toArray + +let processGraphAsync<'Item, 'Result when 'Item: equality and 'Item: comparison> + (graph: Graph<'Item>) + (work: ('Item -> ProcessedNode<'Item, 'Result>) -> NodeInfo<'Item> -> Async<'Result>) + : Async<('Item * 'Result)[]> = + async { + let transitiveDeps = graph |> Graph.transitive + let dependants = graph |> Graph.reverse + // Cancellation source used to signal either an exception in one of the items or end of processing. + let! parentCt = Async.CancellationToken + use localCts = new CancellationTokenSource() + + let completionSignal = TaskCompletionSource() + + use _ = parentCt.Register(fun () -> completionSignal.TrySetCanceled() |> ignore) + + use cts = CancellationTokenSource.CreateLinkedTokenSource(parentCt, localCts.Token) + + let makeNode (item: 'Item) : GraphNode<'Item, 'Result> = + let info = + let exists = graph.ContainsKey item + + if + not exists + || not (transitiveDeps.ContainsKey item) + || not (dependants.ContainsKey item) + then + printfn $"Unexpected inconsistent state of the graph for item '{item}'" + + { + Item = item + Deps = graph[item] + TransitiveDeps = transitiveDeps[item] + Dependants = dependants[item] + } + + { + Info = info + Result = None + ProcessedDepsCount = IncrementableInt(0) + } + + let nodes = graph.Keys |> Seq.map (fun item -> item, makeNode item) |> readOnlyDict + + let lookupMany items = + items |> Array.map (fun item -> nodes[item]) + + let leaves = + nodes.Values |> Seq.filter (fun n -> n.Info.Deps.Length = 0) |> Seq.toArray + + let getItemPublicNode item = + let node = nodes[item] + + { + ProcessedNode.Info = node.Info + ProcessedNode.Result = + node.Result + |> Option.defaultWith (fun () -> failwith $"Results for item '{node.Info.Item}' are not yet available") + } + + let processedCount = IncrementableInt(0) + + let raiseExn (item, ex: exn) = + localCts.Cancel() + + match ex with + | :? OperationCanceledException -> completionSignal.TrySetCanceled() + | _ -> + completionSignal.TrySetException( + GraphProcessingException($"[*] Encountered exception when processing item '{item}': {ex.Message}", ex) + ) + |> ignore + + let incrementProcessedNodesCount () = + if processedCount.Increment() = nodes.Count then + completionSignal.TrySetResult() |> ignore + + let rec queueNode node = + Async.Start( + async { + let! res = processNode node |> Async.Catch + + match res with + | Choice1Of2() -> () + | Choice2Of2 ex -> raiseExn (node.Info.Item, ex) + }, + cts.Token + ) + + and processNode (node: GraphNode<'Item, 'Result>) : Async = + async { + + let info = node.Info + + let! singleRes = work getItemPublicNode info + node.Result <- Some singleRes + + let unblockedDependants = + node.Info.Dependants + |> lookupMany + // For every dependant, increment its number of processed dependencies, + // and filter dependants which now have all dependencies processed (but didn't before). + |> Array.filter (fun dependant -> + let pdc = dependant.ProcessedDepsCount.Increment() + // Note: We cannot read 'dependant.ProcessedDepsCount' again to avoid returning the same item multiple times. + pdc = dependant.Info.Deps.Length) + + unblockedDependants |> Array.iter queueNode + incrementProcessedNodesCount () + } + + leaves |> Array.iter queueNode + + // Wait for end of processing, an exception, or an external cancellation request. + do! completionSignal.Task |> Async.AwaitTask + + // All calculations succeeded - extract the results and sort in input order. + return + nodes.Values + |> Seq.map (fun node -> + let result = + node.Result + |> Option.defaultWith (fun () -> failwith $"Unexpected lack of result for item '{node.Info.Item}'") + + node.Info.Item, result) + |> Seq.sortBy fst + |> Seq.toArray + } diff --git a/src/Compiler/Driver/GraphChecking/GraphProcessing.fsi b/src/Compiler/Driver/GraphChecking/GraphProcessing.fsi index cb9a95a59f8..585daa52fd7 100644 --- a/src/Compiler/Driver/GraphChecking/GraphProcessing.fsi +++ b/src/Compiler/Driver/GraphChecking/GraphProcessing.fsi @@ -15,6 +15,10 @@ type ProcessedNode<'Item, 'Result> = { Info: NodeInfo<'Item> Result: 'Result } +type GraphProcessingException = + inherit exn + new: msg: string * ex: System.Exception -> GraphProcessingException + /// /// A generic method to generate results for a graph of work items in parallel. /// Processes leaves first, and after each node has been processed, schedules any now unblocked dependants. @@ -33,3 +37,8 @@ val processGraph<'Item, 'Result when 'Item: equality and 'Item: comparison> : work: (('Item -> ProcessedNode<'Item, 'Result>) -> NodeInfo<'Item> -> 'Result) -> parentCt: CancellationToken -> ('Item * 'Result)[] + +val processGraphAsync<'Item, 'Result when 'Item: equality and 'Item: comparison> : + graph: Graph<'Item> -> + work: (('Item -> ProcessedNode<'Item, 'Result>) -> NodeInfo<'Item> -> Async<'Result>) -> + Async<('Item * 'Result)[]> diff --git a/src/Compiler/Driver/GraphChecking/Types.fs b/src/Compiler/Driver/GraphChecking/Types.fs index 00538b6e599..c667a573f69 100644 --- a/src/Compiler/Driver/GraphChecking/Types.fs +++ b/src/Compiler/Driver/GraphChecking/Types.fs @@ -73,6 +73,9 @@ type internal FileContentEntry = /// Being explicit about nested modules allows for easier reasoning what namespaces (paths) are open. /// We can scope an `OpenStatement` to the everything that is happening inside the nested module. | NestedModule of name: string * nestedContent: FileContentEntry list + /// A single identifier that could be the name of a module. + /// Example use-case: `let x = nameof Foo` where `Foo` is a module. + | ModuleName of name: Identifier type internal FileContent = { diff --git a/src/Compiler/Driver/GraphChecking/Types.fsi b/src/Compiler/Driver/GraphChecking/Types.fsi index 468ef65889c..096719b6be7 100644 --- a/src/Compiler/Driver/GraphChecking/Types.fsi +++ b/src/Compiler/Driver/GraphChecking/Types.fsi @@ -67,6 +67,9 @@ type internal FileContentEntry = /// Being explicit about nested modules allows for easier reasoning what namespaces (paths) are open. /// For example we can limit the scope of an `OpenStatement` to symbols defined inside the nested module. | NestedModule of name: string * nestedContent: FileContentEntry list + /// A single identifier that could be the name of a module. + /// Example use-case: `let x = nameof Foo` where `Foo` is a module. + | ModuleName of name: Identifier /// File identifiers and its content extract for dependency resolution type internal FileContent = diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fs b/src/Compiler/Driver/ParseAndCheckInputs.fs index a9fc59b66d3..5a23c95ca7b 100644 --- a/src/Compiler/Driver/ParseAndCheckInputs.fs +++ b/src/Compiler/Driver/ParseAndCheckInputs.fs @@ -1483,7 +1483,7 @@ let CheckOneInputWithCallback prefixPathOpt, tcSink, tcState: TcState, - inp: ParsedInput, + input: ParsedInput, _skipImplIfSigExists: bool): (unit -> bool) * TcConfig * TcImports * TcGlobals * LongIdent option * TcResultsSink * TcState * ParsedInput * bool) : Cancellable> = @@ -1491,7 +1491,7 @@ let CheckOneInputWithCallback try CheckSimulateException tcConfig - let m = inp.Range + let m = input.Range let amap = tcImports.GetImportMap() let conditionalDefines = @@ -1500,7 +1500,7 @@ let CheckOneInputWithCallback else Some tcConfig.conditionalDefines - match inp with + match input with | ParsedInput.SigFile file -> let qualNameOfFile = file.QualifiedName @@ -1740,6 +1740,43 @@ module private TypeCheckingGraphProcessing = finalFileResults, state +let TransformDependencyGraph (graph: Graph, filePairs: FilePairMap) = + let mkArtificialImplFile n = NodeToTypeCheck.ArtificialImplFile n + let mkPhysicalFile n = NodeToTypeCheck.PhysicalFile n + + /// Map any signature dependencies to the ArtificialImplFile counterparts, + /// unless the signature dependency is the backing file of the current (implementation) file. + let mapDependencies idx deps = + Array.map + (fun dep -> + if filePairs.IsSignature dep then + let implIdx = filePairs.GetImplementationIndex dep + + if implIdx = idx then + // This is the matching signature for the implementation. + // Retain the direct dependency onto the signature file. + mkPhysicalFile dep + else + mkArtificialImplFile dep + else + mkPhysicalFile dep) + deps + + // Transform the graph to include ArtificialImplFile nodes when necessary. + graph + |> Seq.collect (fun (KeyValue(fileIdx, deps)) -> + if filePairs.IsSignature fileIdx then + // Add an additional ArtificialImplFile node for the signature file. + [| + // Mark the current file as physical and map the dependencies. + mkPhysicalFile fileIdx, mapDependencies fileIdx deps + // Introduce a new node that depends on the signature. + mkArtificialImplFile fileIdx, [| mkPhysicalFile fileIdx |] + |] + else + [| mkPhysicalFile fileIdx, mapDependencies fileIdx deps |]) + |> Graph.make + /// Constructs a file dependency graph and type-checks the files in parallel where possible. let CheckMultipleInputsUsingGraphMode ((ctok, checkForErrors, tcConfig: TcConfig, tcImports: TcImports, tcGlobals, prefixPathOpt, tcState, eagerFormat, inputs): @@ -1768,42 +1805,7 @@ let CheckMultipleInputsUsingGraphMode let filePairs = FilePairMap(sourceFiles) let graph, trie = DependencyResolution.mkGraph filePairs sourceFiles - let nodeGraph = - let mkArtificialImplFile n = NodeToTypeCheck.ArtificialImplFile n - let mkPhysicalFile n = NodeToTypeCheck.PhysicalFile n - - /// Map any signature dependencies to the ArtificialImplFile counterparts, - /// unless the signature dependency is the backing file of the current (implementation) file. - let mapDependencies idx deps = - Array.map - (fun dep -> - if filePairs.IsSignature dep then - let implIdx = filePairs.GetImplementationIndex dep - - if implIdx = idx then - // This is the matching signature for the implementation. - // Retain the direct dependency onto the signature file. - mkPhysicalFile dep - else - mkArtificialImplFile dep - else - mkPhysicalFile dep) - deps - - // Transform the graph to include ArtificialImplFile nodes when necessary. - graph - |> Seq.collect (fun (KeyValue(fileIdx, deps)) -> - if filePairs.IsSignature fileIdx then - // Add an additional ArtificialImplFile node for the signature file. - [| - // Mark the current file as physical and map the dependencies. - mkPhysicalFile fileIdx, mapDependencies fileIdx deps - // Introduce a new node that depends on the signature. - mkArtificialImplFile fileIdx, [| mkPhysicalFile fileIdx |] - |] - else - [| mkPhysicalFile fileIdx, mapDependencies fileIdx deps |]) - |> Graph.make + let nodeGraph = TransformDependencyGraph(graph, filePairs) // Persist the graph to a Mermaid diagram if specified. if tcConfig.typeCheckingConfig.DumpGraph then @@ -1823,7 +1825,7 @@ let CheckMultipleInputsUsingGraphMode .TrimStart([| '\\'; '/' |]) (idx, friendlyFileName)) - |> Graph.serialiseToMermaid graphFile) + |> Graph.writeMermaidToFile graphFile) let _ = ctok // TODO Use it let diagnosticsLogger = DiagnosticsThreadStatics.DiagnosticsLogger diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fsi b/src/Compiler/Driver/ParseAndCheckInputs.fsi index 745afa51be4..875be616a8e 100644 --- a/src/Compiler/Driver/ParseAndCheckInputs.fsi +++ b/src/Compiler/Driver/ParseAndCheckInputs.fsi @@ -13,12 +13,44 @@ open FSharp.Compiler.CompilerImports open FSharp.Compiler.Diagnostics open FSharp.Compiler.DependencyManager open FSharp.Compiler.DiagnosticsLogger +open FSharp.Compiler.GraphChecking +open FSharp.Compiler.NameResolution open FSharp.Compiler.Syntax open FSharp.Compiler.TcGlobals open FSharp.Compiler.Text open FSharp.Compiler.TypedTree open FSharp.Compiler.UnicodeLexing +/// Auxiliary type for re-using signature information in TcEnvFromImpls. +/// +/// TcState has two typing environments: TcEnvFromSignatures && TcEnvFromImpls +/// When type checking a file, depending on the type (implementation or signature), it will use one of these typing environments (TcEnv). +/// Checking a file will populate the respective TcEnv. +/// +/// When a file has a dependencies, the information of the signature file in case a pair (implementation file backed by a signature) will suffice to type-check that file. +/// Example: if `B.fs` has a dependency on `A`, the information of `A.fsi` is enough for `B.fs` to type-check, on condition that information is available in the TcEnvFromImpls. +/// We introduce a special ArtificialImplFile node in the graph to satisfy this. `B.fs -> [ A.fsi ]` becomes `B.fs -> [ ArtificialImplFile A ]. +/// The `ArtificialImplFile A` node will duplicate the signature information which A.fsi provided earlier. +/// Processing a `ArtificialImplFile` node will add the information from the TcEnvFromSignatures to the TcEnvFromImpls. +/// This means `A` will be known in both TcEnvs and therefor `B.fs` can be type-checked. +/// By doing this, we can speed up the graph processing as type checking a signature file is less expensive than its implementation counterpart. +/// +/// When we need to actually type-check an implementation file backed by a signature, we cannot have the duplicate information of the signature file present in TcEnvFromImpls. +/// Example `A.fs -> [ A.fsi ]`. An implementation file always depends on its signature. +/// Type-checking `A.fs` will add the actual information to TcEnvFromImpls and we do not depend on the `ArtificialImplFile A` for `A.fs`. +/// +/// In order to deal correctly with the `ArtificialImplFile` logic, we need to transform the resolved graph to contain the additional pair nodes. +/// After we have type-checked the graph, we exclude the ArtificialImplFile nodes as they are not actual physical files in our project. +[] +type NodeToTypeCheck = + /// A real physical file in the current project. + /// This can be either an implementation or a signature file. + | PhysicalFile of fileIndex: FileIndex + /// An artificial node that will add the earlier processed signature information to the TcEnvFromImpls. + /// Dependants on this type of node will perceive that a file is known in both TcEnvFromSignatures and TcEnvFromImpls. + /// Even though the actual implementation file was not type-checked. + | ArtificialImplFile of signatureFileIndex: FileIndex + val IsScript: string -> bool val ComputeQualifiedNameOfFileFromUniquePath: range * string list -> QualifiedNameOfFile @@ -131,6 +163,8 @@ type TcState = member CreatesGeneratedProvidedTypes: bool +type PartialResult = TcEnv * TopAttribs * CheckedImplFile option * ModuleOrNamespaceType + /// Get the initial type checking state for a set of inputs val GetInitialTcState: range * string * TcConfig * TcGlobals * TcImports * TcEnv * OpenDeclaration list -> TcState @@ -151,6 +185,42 @@ val CheckOneInput: input: ParsedInput -> Cancellable<(TcEnv * TopAttribs * CheckedImplFile option * ModuleOrNamespaceType) * TcState> +val CheckOneInputWithCallback: + node: NodeToTypeCheck -> + checkForErrors: (unit -> bool) * + tcConfig: TcConfig * + tcImports: TcImports * + tcGlobals: TcGlobals * + prefixPathOpt: LongIdent option * + tcSink: TcResultsSink * + tcState: TcState * + input: ParsedInput * + _skipImplIfSigExists: bool -> + Cancellable> + +val AddCheckResultsToTcState: + tcGlobals: TcGlobals * + amap: Import.ImportMap * + hadSig: bool * + prefixPathOpt: LongIdent option * + tcSink: TcResultsSink * + tcImplEnv: TcEnv * + qualNameOfFile: QualifiedNameOfFile * + implFileSigType: ModuleOrNamespaceType -> + tcState: TcState -> + ModuleOrNamespaceType * TcState + +val AddSignatureResultToTcImplEnv: + tcImports: TcImports * + tcGlobals: TcGlobals * + prefixPathOpt: LongIdent option * + tcSink: TcResultsSink * + tcState: TcState * + input: ParsedInput -> + (TcState -> PartialResult * TcState) + +val TransformDependencyGraph: graph: Graph * filePairs: FilePairMap -> Graph + /// Finish the checking of multiple inputs val CheckMultipleInputsFinish: (TcEnv * TopAttribs * 'T option * 'U) list * TcState -> (TcEnv * TopAttribs * 'T list * 'U list) * TcState diff --git a/src/Compiler/Driver/fsc.fs b/src/Compiler/Driver/fsc.fs index d3bfd2e74cc..eab380bae5c 100644 --- a/src/Compiler/Driver/fsc.fs +++ b/src/Compiler/Driver/fsc.fs @@ -349,7 +349,7 @@ module InterfaceFileWriter = let writeAllToSameFile declaredImpls = /// Use a UTF-8 Encoding with no Byte Order Mark let os = - if tcConfig.printSignatureFile = "" then + if String.IsNullOrEmpty(tcConfig.printSignatureFile) then Console.Out else FileSystem diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 3eba9541293..b6211ffaea5 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -315,6 +315,7 @@ csExpectTypeWithOperatorButGivenFunction,"Expecting a type supporting the operat csExpectTypeWithOperatorButGivenTuple,"Expecting a type supporting the operator '%s' but given a tuple type" csTypesDoNotSupportOperator,"None of the types '%s' support the operator '%s'" csTypeDoesNotSupportOperator,"The type '%s' does not support the operator '%s'" +csFunctionDoesNotSupportType,"'%s' does not support the type '%s', because the latter lacks the required (real or built-in) member '%s'" csTypesDoNotSupportOperatorNullable,"None of the types '%s' support the operator '%s'. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'." csTypeDoesNotSupportOperatorNullable,"The type '%s' does not support the operator '%s'. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'." csTypeDoesNotSupportConversion,"The type '%s' does not support a conversion to the type '%s'" @@ -1750,4 +1751,6 @@ featureReuseSameFieldsInStructUnions,"Share underlying fields in a [] di 3860,chkStaticMembersOnObjectExpressions,"Object expressions cannot implement interfaces with static abstract members or declare static members." 3861,chkTailCallAttrOnNonRec,"The TailCall attribute should only be applied to recursive functions." 3862,parsStaticMemberImcompleteSyntax,"Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration." -3863,parsExpectingField,"Expecting record field" \ No newline at end of file +3863,parsExpectingField,"Expecting record field" +3864,tooManyMethodsInDotNetTypeWritingAssembly,"The type '%s' has too many methods. Found: '%d', maximum: '%d'" +3865,parsOnlySimplePatternsAreAllowedInConstructors,"Only simple patterns are allowed in primary constructors" \ No newline at end of file diff --git a/src/Compiler/FSStrings.resx b/src/Compiler/FSStrings.resx index 60558f2e35b..e0a53a33ae1 100644 --- a/src/Compiler/FSStrings.resx +++ b/src/Compiler/FSStrings.resx @@ -1044,20 +1044,11 @@ The following fields require values: {0} - - Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. + + Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f<'a>"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -> obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. - - Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - - - Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved. - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. + + Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x<'a>".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. syntax error diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj index 65c00a7702d..61fcb193a1a 100644 --- a/src/Compiler/FSharp.Compiler.Service.fsproj +++ b/src/Compiler/FSharp.Compiler.Service.fsproj @@ -21,6 +21,7 @@ $(OtherFlags) --warnon:3218 $(OtherFlags) --warnon:3390 + true $(IntermediateOutputPath)$(TargetFramework)\ $(IntermediateOutputPath)$(TargetFramework)\ @@ -76,7 +77,8 @@ - + + @@ -90,6 +92,7 @@ FSStrings.resx FSStrings.resources + @@ -124,6 +127,8 @@ + + @@ -144,6 +149,8 @@ + + @@ -156,6 +163,8 @@ + + @@ -475,6 +484,10 @@ + + + + @@ -492,7 +505,12 @@ - + + + + + + diff --git a/src/Compiler/Facilities/AsyncMemoize.fs b/src/Compiler/Facilities/AsyncMemoize.fs new file mode 100644 index 00000000000..8309eaa1c15 --- /dev/null +++ b/src/Compiler/Facilities/AsyncMemoize.fs @@ -0,0 +1,610 @@ +namespace Internal.Utilities.Collections + +open System +open System.Collections.Generic +open System.Diagnostics +open System.IO +open System.Threading +open System.Threading.Tasks + +open FSharp.Compiler +open FSharp.Compiler.BuildGraph +open FSharp.Compiler.Diagnostics +open FSharp.Compiler.DiagnosticsLogger +open System.Runtime.CompilerServices + +[] +module internal Utils = + + /// Return file name with one directory above it + let shortPath path = + let dirPath = Path.GetDirectoryName path + + let dir = + dirPath.Split Path.DirectorySeparatorChar + |> Array.tryLast + |> Option.map (sprintf "%s/") + |> Option.defaultValue "" + + $"{dir}{Path.GetFileName path}" + + let replayDiagnostics (logger: DiagnosticsLogger) = Seq.iter ((<|) logger.DiagnosticSink) + + let (|TaskCancelled|_|) (ex: exn) = + match ex with + | :? System.Threading.Tasks.TaskCanceledException as tce -> Some tce + //| :? System.AggregateException as ae -> + // if ae.InnerExceptions |> Seq.forall (fun e -> e :? System.Threading.Tasks.TaskCanceledException) then + // ae.InnerExceptions |> Seq.tryHead |> Option.map (fun e -> e :?> System.Threading.Tasks.TaskCanceledException) + // else + // None + | _ -> None + +type internal StateUpdate<'TValue> = + | CancelRequest + | OriginatorCanceled + | JobCompleted of 'TValue * (PhasedDiagnostic * FSharpDiagnosticSeverity) list + | JobFailed of exn * (PhasedDiagnostic * FSharpDiagnosticSeverity) list + +type internal MemoizeReply<'TValue> = + | New of CancellationToken + | Existing of Task<'TValue> + +type internal MemoizeRequest<'TValue> = GetOrCompute of NodeCode<'TValue> * CancellationToken + +[] +type internal Job<'TValue> = + | Running of TaskCompletionSource<'TValue> * CancellationTokenSource * NodeCode<'TValue> * DateTime * ResizeArray + | Completed of 'TValue * (PhasedDiagnostic * FSharpDiagnosticSeverity) list + | Canceled of DateTime + | Failed of DateTime * exn // TODO: probably we don't need to keep this + + member this.DebuggerDisplay = + match this with + | Running(_, cts, _, ts, _) -> + let cancellation = + if cts.IsCancellationRequested then + " ! Cancellation Requested" + else + "" + + $"Running since {ts.ToShortTimeString()}{cancellation}" + | Completed(value, diags) -> $"Completed {value}" + (if diags.Length > 0 then $" ({diags.Length})" else "") + | Canceled _ -> "Canceled" + | Failed(_, ex) -> $"Failed {ex}" + +type internal JobEvent = + | Started + | Finished + | Canceled + | Evicted + | Collected + | Weakened + | Strengthened + | Failed + | Cleared + +type internal ICacheKey<'TKey, 'TVersion> = + abstract member GetKey: unit -> 'TKey + abstract member GetVersion: unit -> 'TVersion + abstract member GetLabel: unit -> string + +[] +type Extensions = + + [] + static member internal WithExtraVersion(cacheKey: ICacheKey<_, _>, extraVersion) = + { new ICacheKey<_, _> with + member _.GetLabel() = cacheKey.GetLabel() + member _.GetKey() = cacheKey.GetKey() + member _.GetVersion() = cacheKey.GetVersion(), extraVersion + } + +type private KeyData<'TKey, 'TVersion> = + { + Label: string + Key: 'TKey + Version: 'TVersion + } + +type internal AsyncLock() = + + let semaphore = new SemaphoreSlim(1, 1) + + member _.Semaphore = semaphore + + member _.Do(f) = + task { + do! semaphore.WaitAsync() + + try + return! f () + finally + semaphore.Release() |> ignore + } + + interface IDisposable with + member _.Dispose() = semaphore.Dispose() + +type internal CachingDiagnosticsLogger(originalLogger: DiagnosticsLogger option) = + inherit DiagnosticsLogger($"CachingDiagnosticsLogger") + + let capturedDiagnostics = ResizeArray() + + override _.ErrorCount = + originalLogger + |> Option.map (fun x -> x.ErrorCount) + |> Option.defaultValue capturedDiagnostics.Count + + override _.DiagnosticSink(diagnostic: PhasedDiagnostic, severity: FSharpDiagnosticSeverity) = + originalLogger |> Option.iter (fun x -> x.DiagnosticSink(diagnostic, severity)) + capturedDiagnostics.Add(diagnostic, severity) + + member _.CapturedDiagnostics = capturedDiagnostics |> Seq.toList + +[] +type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'TVersion: equality> + (?keepStrongly, ?keepWeakly, ?name: string, ?cancelDuplicateRunningJobs: bool) = + + let name = defaultArg name "N/A" + let cancelDuplicateRunningJobs = defaultArg cancelDuplicateRunningJobs false + + let event = Event<_>() + + let mutable errors = 0 + let mutable hits = 0 + let mutable started = 0 + let mutable completed = 0 + let mutable canceled = 0 + let mutable restarted = 0 + let mutable failed = 0 + let mutable evicted = 0 + let mutable collected = 0 + let mutable strengthened = 0 + let mutable cleared = 0 + + let mutable cancel_ct_registration_original = 0 + let mutable cancel_exception_original = 0 + let mutable cancel_original_processed = 0 + let mutable cancel_ct_registration_subsequent = 0 + let mutable cancel_exception_subsequent = 0 + let mutable cancel_subsequent_processed = 0 + + let failures = ResizeArray() + let mutable avgDurationMs = 0.0 + + let cache = + LruCache<'TKey, 'TVersion, Job<'TValue>>( + keepStrongly = defaultArg keepStrongly 100, + keepWeakly = defaultArg keepWeakly 200, + requiredToKeep = + (function + | Running _ -> true + | Job.Canceled at when at > DateTime.Now.AddMinutes -5.0 -> true + | Job.Failed(at, _) when at > DateTime.Now.AddMinutes -5.0 -> true + | _ -> false), + event = + (function + | CacheEvent.Evicted -> + (fun k -> + Interlocked.Increment &evicted |> ignore + event.Trigger(JobEvent.Evicted, k)) + | CacheEvent.Collected -> + (fun k -> + Interlocked.Increment &collected |> ignore + event.Trigger(JobEvent.Collected, k)) + | CacheEvent.Weakened -> (fun k -> event.Trigger(JobEvent.Weakened, k)) + | CacheEvent.Strengthened -> + (fun k -> + Interlocked.Increment &strengthened |> ignore + event.Trigger(JobEvent.Strengthened, k)) + | CacheEvent.Cleared -> + (fun k -> + Interlocked.Increment &cleared |> ignore + event.Trigger(JobEvent.Cleared, k))) + ) + + let requestCounts = Dictionary, int>() + let cancellationRegistrations = Dictionary<_, _>() + + let saveRegistration key registration = + cancellationRegistrations[key] <- + match cancellationRegistrations.TryGetValue key with + | true, registrations -> registration :: registrations + | _ -> [ registration ] + + let cancelRegistration key = + match cancellationRegistrations.TryGetValue key with + | true, registrations -> + for r: CancellationTokenRegistration in registrations do + r.Dispose() + + cancellationRegistrations.Remove key |> ignore + | _ -> () + + let incrRequestCount key = + requestCounts[key] <- + if requestCounts.ContainsKey key then + requestCounts[key] + 1 + else + 1 + + let decrRequestCount key = + if requestCounts.ContainsKey key then + requestCounts[key] <- requestCounts[key] - 1 + + let log (eventType, keyData: KeyData<_, _>) = + event.Trigger(eventType, (keyData.Label, keyData.Key, keyData.Version)) + + let lock = new AsyncLock() + + let processRequest post (key: KeyData<_, _>, msg) diagnosticLogger = + + lock.Do(fun () -> + task { + + let cached, otherVersions = cache.GetAll(key.Key, key.Version) + + return + match msg, cached with + | GetOrCompute _, Some(Completed(result, diags)) -> + Interlocked.Increment &hits |> ignore + diags |> replayDiagnostics diagnosticLogger + Existing(Task.FromResult result) + | GetOrCompute(_, ct), Some(Running(tcs, _, _, _, loggers)) -> + Interlocked.Increment &hits |> ignore + incrRequestCount key + + ct.Register(fun _ -> + let _name = name + Interlocked.Increment &cancel_ct_registration_subsequent |> ignore + post (key, CancelRequest)) + |> saveRegistration key + + loggers.Add diagnosticLogger + + Existing tcs.Task + + | GetOrCompute(computation, ct), None + | GetOrCompute(computation, ct), Some(Job.Canceled _) + | GetOrCompute(computation, ct), Some(Job.Failed _) -> + Interlocked.Increment &started |> ignore + incrRequestCount key + + ct.Register(fun _ -> + let _name = name + Interlocked.Increment &cancel_ct_registration_original |> ignore + post (key, OriginatorCanceled)) + |> saveRegistration key + + let cts = new CancellationTokenSource() + + cache.Set( + key.Key, + key.Version, + key.Label, + (Running(TaskCompletionSource(), cts, computation, DateTime.Now, ResizeArray())) + ) + + otherVersions + |> Seq.choose (function + | v, Running(_tcs, cts, _, _, _) -> Some(v, cts) + | _ -> None) + |> Seq.iter (fun (_v, cts) -> + use _ = Activity.start $"{name}: Duplicate running job" [| "key", key.Label |] + //System.Diagnostics.Trace.TraceWarning($"{name} Duplicate {key.Label}") + if cancelDuplicateRunningJobs then + //System.Diagnostics.Trace.TraceWarning("Canceling") + cts.Cancel()) + + New cts.Token + }) + + let internalError key message = + let ex = exn (message) + failures.Add(key, ex) + Interlocked.Increment &errors |> ignore + // raise ex -- Suppose there's no need to raise here - where does it even go? + + let processStateUpdate post (key: KeyData<_, _>, action: StateUpdate<_>) = + task { + do! Task.Delay 0 + + do! + lock.Do(fun () -> + task { + + let cached = cache.TryGet(key.Key, key.Version) + + match action, cached with + + | OriginatorCanceled, Some(Running(tcs, cts, computation, _, _)) -> + + Interlocked.Increment &cancel_original_processed |> ignore + + decrRequestCount key + + if requestCounts[key] < 1 then + cancelRegistration key + cts.Cancel() + tcs.TrySetCanceled() |> ignore + // Remember the job in case it completes after cancellation + cache.Set(key.Key, key.Version, key.Label, Job.Canceled DateTime.Now) + requestCounts.Remove key |> ignore + log (Canceled, key) + Interlocked.Increment &canceled |> ignore + use _ = Activity.start $"{name}: Canceled job" [| "key", key.Label |] + () + + else + // We need to restart the computation + Task.Run(fun () -> + Async.StartAsTask( + async { + + let cachingLogger = new CachingDiagnosticsLogger(None) + + try + // TODO: Should unify starting and restarting + log (Started, key) + Interlocked.Increment &restarted |> ignore + System.Diagnostics.Trace.TraceInformation $"{name} Restarted {key.Label}" + let currentLogger = DiagnosticsThreadStatics.DiagnosticsLogger + DiagnosticsThreadStatics.DiagnosticsLogger <- cachingLogger + + try + let! result = computation |> Async.AwaitNodeCode + post (key, (JobCompleted(result, cachingLogger.CapturedDiagnostics))) + return () + finally + DiagnosticsThreadStatics.DiagnosticsLogger <- currentLogger + with + | TaskCancelled _ -> + Interlocked.Increment &cancel_exception_subsequent |> ignore + post (key, CancelRequest) + () + | ex -> post (key, (JobFailed(ex, cachingLogger.CapturedDiagnostics))) + } + ), + cts.Token) + |> ignore + + | CancelRequest, Some(Running(tcs, cts, _c, _, _)) -> + + Interlocked.Increment &cancel_subsequent_processed |> ignore + + decrRequestCount key + + if requestCounts[key] < 1 then + cancelRegistration key + cts.Cancel() + tcs.TrySetCanceled() |> ignore + // Remember the job in case it completes after cancellation + cache.Set(key.Key, key.Version, key.Label, Job.Canceled DateTime.Now) + requestCounts.Remove key |> ignore + log (Canceled, key) + Interlocked.Increment &canceled |> ignore + use _ = Activity.start $"{name}: Canceled job" [| "key", key.Label |] + () + + // Probably in some cases cancellation can be fired off even after we just unregistered it + | CancelRequest, None + | CancelRequest, Some(Completed _) + | CancelRequest, Some(Job.Canceled _) + | CancelRequest, Some(Job.Failed _) + | OriginatorCanceled, None + | OriginatorCanceled, Some(Completed _) + | OriginatorCanceled, Some(Job.Canceled _) + | OriginatorCanceled, Some(Job.Failed _) -> () + + | JobFailed(ex, diags), Some(Running(tcs, _cts, _c, _ts, loggers)) -> + cancelRegistration key + cache.Set(key.Key, key.Version, key.Label, Job.Failed(DateTime.Now, ex)) + requestCounts.Remove key |> ignore + log (Failed, key) + Interlocked.Increment &failed |> ignore + failures.Add(key.Label, ex) + + for logger in loggers do + diags |> replayDiagnostics logger + + tcs.TrySetException ex |> ignore + + | JobCompleted(result, diags), Some(Running(tcs, _cts, _c, started, loggers)) -> + cancelRegistration key + cache.Set(key.Key, key.Version, key.Label, (Completed(result, diags))) + requestCounts.Remove key |> ignore + log (Finished, key) + Interlocked.Increment &completed |> ignore + let duration = float (DateTime.Now - started).Milliseconds + + avgDurationMs <- + if completed < 2 then + duration + else + avgDurationMs + (duration - avgDurationMs) / float completed + + for logger in loggers do + diags |> replayDiagnostics logger + + if tcs.TrySetResult result = false then + internalError key.Label "Invalid state: Completed job already completed" + + // Sometimes job can be canceled but it still manages to complete (or fail) + | JobFailed _, Some(Job.Canceled _) + | JobCompleted _, Some(Job.Canceled _) -> () + + // Job can't be evicted from cache while it's running because then subsequent requesters would be waiting forever + | JobFailed _, None -> internalError key.Label "Invalid state: Running job missing in cache (failed)" + + | JobCompleted _, None -> internalError key.Label "Invalid state: Running job missing in cache (completed)" + + | JobFailed(ex, _diags), Some(Completed(_job, _diags2)) -> + internalError key.Label $"Invalid state: Failed Completed job \n%A{ex}" + + | JobCompleted(_result, _diags), Some(Completed(_job, _diags2)) -> + internalError key.Label "Invalid state: Double-Completed job" + + | JobFailed(ex, _diags), Some(Job.Failed(_, ex2)) -> + internalError key.Label $"Invalid state: Double-Failed job \n%A{ex} \n%A{ex2}" + + | JobCompleted(_result, _diags), Some(Job.Failed(_, ex2)) -> + internalError key.Label $"Invalid state: Completed Failed job \n%A{ex2}" + }) + } + + let rec post msg = + Task.Run(fun () -> processStateUpdate post msg :> Task) |> ignore + + member this.Get'(key, computation) = + + let wrappedKey = + { new ICacheKey<_, _> with + member _.GetKey() = key + member _.GetVersion() = Unchecked.defaultof<_> + member _.GetLabel() = key.ToString() + } + + this.Get(wrappedKey, computation) + + member _.Get(key: ICacheKey<_, _>, computation) = + + let key = + { + Label = key.GetLabel() + Key = key.GetKey() + Version = key.GetVersion() + } + + node { + let! ct = NodeCode.CancellationToken + + let callerDiagnosticLogger = DiagnosticsThreadStatics.DiagnosticsLogger + + match! + processRequest post (key, GetOrCompute(computation, ct)) callerDiagnosticLogger + |> NodeCode.AwaitTask + with + | New internalCt -> + + let linkedCtSource = CancellationTokenSource.CreateLinkedTokenSource(ct, internalCt) + let cachingLogger = new CachingDiagnosticsLogger(Some callerDiagnosticLogger) + + try + return! + Async.StartAsTask( + async { + // TODO: Should unify starting and restarting + let currentLogger = DiagnosticsThreadStatics.DiagnosticsLogger + DiagnosticsThreadStatics.DiagnosticsLogger <- cachingLogger + + log (Started, key) + + try + let! result = computation |> Async.AwaitNodeCode + post (key, (JobCompleted(result, cachingLogger.CapturedDiagnostics))) + return result + finally + DiagnosticsThreadStatics.DiagnosticsLogger <- currentLogger + }, + cancellationToken = linkedCtSource.Token + ) + |> NodeCode.AwaitTask + with + | TaskCancelled ex -> + // TODO: do we need to do anything else here? Presumably it should be done by the registration on + // the cancellation token or before we triggered our own cancellation + + // Let's send this again just in case. It seems sometimes it's not triggered from the registration? + + Interlocked.Increment &cancel_exception_original |> ignore + + post (key, (OriginatorCanceled)) + return raise ex + | ex -> + post (key, (JobFailed(ex, cachingLogger.CapturedDiagnostics))) + return raise ex + + | Existing job -> return! job |> NodeCode.AwaitTask + + } + + member _.Clear() = cache.Clear() + + member _.Clear predicate = cache.Clear predicate + + member val Event = event.Publish + + member this.OnEvent = this.Event.Add + + member _.Locked = lock.Semaphore.CurrentCount < 1 + + member _.Running = + cache.GetValues() + |> Seq.filter (function + | _, _, Running _ -> true + | _ -> false) + |> Seq.toArray + + member this.DebuggerDisplay = + let locked = if this.Locked then " [LOCKED]" else "" + + let valueStats = + cache.GetValues() + |> Seq.countBy (function + | _, _, Running _ -> "Running" + | _, _, Completed _ -> "Completed" + | _, _, Job.Canceled _ -> "Canceled" + | _, _, Job.Failed _ -> "Failed") + |> Map + + let running = + valueStats.TryFind "Running" + |> Option.map (sprintf " Running: %d ") + |> Option.defaultValue "" + + let avgDuration = avgDurationMs |> sprintf "| Avg: %.0f ms" + + let hitRatio = + if started > 0 then + $" (%.0f{float hits / (float (started + hits)) * 100.0} %%)" + else + "" + + let stats = + [| + if errors + failed > 0 then + " (_!_) " + if errors > 0 then $"| ERRORS: {errors} " else "" + if failed > 0 then $"| FAILED: {failed} " else "" + $"| hits: {hits}{hitRatio} " + if started > 0 then $"| started: {started} " else "" + if completed > 0 then $"| completed: {completed} " else "" + if canceled > 0 then $"| canceled: {canceled} " else "" + if restarted > 0 then $"| restarted: {restarted} " else "" + if evicted > 0 then $"| evicted: {evicted} " else "" + if collected > 0 then $"| collected: {collected} " else "" + if cleared > 0 then $"| cleared: {cleared} " else "" + if strengthened > 0 then + $"| strengthened: {strengthened} " + else + "" + |] + |> String.concat "" + + $"{locked}{running}{cache.DebuggerDisplay} {stats}{avgDuration}" + +/// A drop-in replacement for AsyncMemoize that disables caching and just runs the computation every time. +[] +type internal AsyncMemoizeDisabled<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'TVersion: equality> + (?keepStrongly, ?keepWeakly, ?name: string, ?cancelDuplicateRunningJobs: bool) = + + do ignore (keepStrongly, keepWeakly, name, cancelDuplicateRunningJobs) + + let mutable requests = 0 + + member _.Get(_key: ICacheKey<_, _>, computation) = + Interlocked.Increment &requests |> ignore + computation + + member _.DebuggerDisplay = $"(disabled) requests: {requests}" diff --git a/src/Compiler/Facilities/AsyncMemoize.fsi b/src/Compiler/Facilities/AsyncMemoize.fsi new file mode 100644 index 00000000000..a142605ac22 --- /dev/null +++ b/src/Compiler/Facilities/AsyncMemoize.fsi @@ -0,0 +1,81 @@ +namespace Internal.Utilities.Collections + +open System.Threading.Tasks +open FSharp.Compiler.BuildGraph + +[] +module internal Utils = + + /// Return file name with one directory above it + val shortPath: path: string -> string + + val (|TaskCancelled|_|): ex: exn -> TaskCanceledException option + +type internal JobEvent = + | Started + | Finished + | Canceled + | Evicted + | Collected + | Weakened + | Strengthened + | Failed + | Cleared + +type internal ICacheKey<'TKey, 'TVersion> = + + abstract GetKey: unit -> 'TKey + + abstract GetLabel: unit -> string + + abstract GetVersion: unit -> 'TVersion + +[] +type Extensions = + + [] + static member internal WithExtraVersion: cacheKey: ICacheKey<'a, 'b> * extraVersion: 'c -> ICacheKey<'a, ('b * 'c)> + +type internal AsyncLock = + interface System.IDisposable + + new: unit -> AsyncLock + + member Do: f: (unit -> #Task<'b>) -> Task<'b> + +/// +/// A cache/memoization for computations that makes sure that the same computation wil only be computed once even if it's needed +/// at multiple places/times. +/// +/// Strongly holds at most one result per key. +/// +type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'TVersion: equality> = + + /// Maximum number of strongly held results to keep in the cache + /// Maximum number of weakly held results to keep in the cache + /// Name of the cache - used in tracing messages + /// If true, when a job is started, all other jobs with the same key will be canceled. + new: + ?keepStrongly: int * ?keepWeakly: int * ?name: string * ?cancelDuplicateRunningJobs: bool -> + AsyncMemoize<'TKey, 'TVersion, 'TValue> + + member Clear: unit -> unit + + member Clear: predicate: ('TKey -> bool) -> unit + + member Get: key: ICacheKey<'TKey, 'TVersion> * computation: NodeCode<'TValue> -> NodeCode<'TValue> + + member Get': key: 'TKey * computation: NodeCode<'TValue> -> NodeCode<'TValue> + + member Event: IEvent + + member OnEvent: ((JobEvent * (string * 'TKey * 'TVersion) -> unit) -> unit) + +/// A drop-in replacement for AsyncMemoize that disables caching and just runs the computation every time. +type internal AsyncMemoizeDisabled<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'TVersion: equality> = + + new: + ?keepStrongly: obj * ?keepWeakly: obj * ?name: string * ?cancelDuplicateRunningJobs: bool -> + AsyncMemoizeDisabled<'TKey, 'TVersion, 'TValue> + + member Get: _key: ICacheKey<'a, 'b> * computation: 'c -> 'c diff --git a/src/Compiler/Facilities/BuildGraph.fs b/src/Compiler/Facilities/BuildGraph.fs index 8927862c23c..1df58c1024b 100644 --- a/src/Compiler/Facilities/BuildGraph.fs +++ b/src/Compiler/Facilities/BuildGraph.fs @@ -17,14 +17,12 @@ let wrapThreadStaticInfo computation = async { let diagnosticsLogger = DiagnosticsThreadStatics.DiagnosticsLogger let phase = DiagnosticsThreadStatics.BuildPhase - let ct = Cancellable.Token try return! computation finally DiagnosticsThreadStatics.DiagnosticsLogger <- diagnosticsLogger DiagnosticsThreadStatics.BuildPhase <- phase - Cancellable.Token <- ct } type Async<'T> with @@ -127,7 +125,6 @@ type NodeCode private () = static member RunImmediate(computation: NodeCode<'T>, ct: CancellationToken) = let diagnosticsLogger = DiagnosticsThreadStatics.DiagnosticsLogger let phase = DiagnosticsThreadStatics.BuildPhase - let ct2 = Cancellable.Token try try @@ -135,7 +132,6 @@ type NodeCode private () = async { DiagnosticsThreadStatics.DiagnosticsLogger <- diagnosticsLogger DiagnosticsThreadStatics.BuildPhase <- phase - Cancellable.Token <- ct2 return! computation |> Async.AwaitNodeCode } @@ -143,7 +139,6 @@ type NodeCode private () = finally DiagnosticsThreadStatics.DiagnosticsLogger <- diagnosticsLogger DiagnosticsThreadStatics.BuildPhase <- phase - Cancellable.Token <- ct2 with :? AggregateException as ex when ex.InnerExceptions.Count = 1 -> raise (ex.InnerExceptions[0]) @@ -153,14 +148,12 @@ type NodeCode private () = static member StartAsTask_ForTesting(computation: NodeCode<'T>, ?ct: CancellationToken) = let diagnosticsLogger = DiagnosticsThreadStatics.DiagnosticsLogger let phase = DiagnosticsThreadStatics.BuildPhase - let ct2 = Cancellable.Token try let work = async { DiagnosticsThreadStatics.DiagnosticsLogger <- diagnosticsLogger DiagnosticsThreadStatics.BuildPhase <- phase - Cancellable.Token <- ct2 return! computation |> Async.AwaitNodeCode } @@ -168,7 +161,6 @@ type NodeCode private () = finally DiagnosticsThreadStatics.DiagnosticsLogger <- diagnosticsLogger DiagnosticsThreadStatics.BuildPhase <- phase - Cancellable.Token <- ct2 static member CancellationToken = cancellationToken diff --git a/src/Compiler/Facilities/CompilerLocation.fs b/src/Compiler/Facilities/CompilerLocation.fs index fa49445b769..11f944c5f30 100644 --- a/src/Compiler/Facilities/CompilerLocation.fs +++ b/src/Compiler/Facilities/CompilerLocation.fs @@ -28,8 +28,7 @@ module internal FSharpEnvironment = let FSharpCoreLibRunningVersion = try match versionOf with - | null -> None - | "" -> None + | s when String.IsNullOrEmpty(s) -> None | s -> Some(s) with _ -> None @@ -184,7 +183,7 @@ module internal FSharpEnvironment = | None -> () | Some(p: string) -> match Path.GetDirectoryName(p) with - | s when s = "" || isNull s || Path.GetFileName(p) = "packages" || s = p -> () + | s when String.IsNullOrEmpty(s) || Path.GetFileName(p) = "packages" || s = p -> () | parentDir -> yield! searchParentDirChain (Some parentDir) assemblyName for p in searchToolPaths path compilerToolPaths do diff --git a/src/Compiler/Facilities/DiagnosticsLogger.fs b/src/Compiler/Facilities/DiagnosticsLogger.fs index 24f6ebf2e6d..08a46d1a25d 100644 --- a/src/Compiler/Facilities/DiagnosticsLogger.fs +++ b/src/Compiler/Facilities/DiagnosticsLogger.fs @@ -374,7 +374,7 @@ type CapturingDiagnosticsLogger(nm, ?eagerFormat) = let errors = diagnostics.ToArray() errors |> Array.iter diagnosticsLogger.DiagnosticSink -/// Type holds thread-static globals for use by the compile. +/// Type holds thread-static globals for use by the compiler. type internal DiagnosticsThreadStatics = [] static val mutable private buildPhase: BuildPhase diff --git a/src/Compiler/Facilities/Hashing.fs b/src/Compiler/Facilities/Hashing.fs new file mode 100644 index 00000000000..2dfbb38b7ee --- /dev/null +++ b/src/Compiler/Facilities/Hashing.fs @@ -0,0 +1,81 @@ +namespace Internal.Utilities.Hashing + +open System +open System.Threading + +/// Tools for hashing things with MD5 into a string that can be used as a cache key. +module internal Md5StringHasher = + + let private md5 = + new ThreadLocal<_>(fun () -> System.Security.Cryptography.MD5.Create()) + + let private computeHash (bytes: byte array) = md5.Value.ComputeHash(bytes) + + let hashString (s: string) = + System.Text.Encoding.UTF8.GetBytes(s) |> computeHash + + let empty = String.Empty + + let addBytes (bytes: byte array) (s: string) = + let sbytes = s |> hashString + + Array.append sbytes bytes + |> computeHash + |> System.BitConverter.ToString + |> (fun x -> x.Replace("-", "")) + + let addString (s: string) (s2: string) = + s |> System.Text.Encoding.UTF8.GetBytes |> addBytes <| s2 + + let addSeq<'item> (items: 'item seq) (addItem: 'item -> string -> string) (s: string) = + items |> Seq.fold (fun s a -> addItem a s) s + + let addStrings strings = addSeq strings addString + + // If we use this make it an extension method? + //let addVersions<'a, 'b when 'a :> ICacheKey<'b, string>> (versions: 'a seq) (s: string) = + // versions |> Seq.map (fun x -> x.GetVersion()) |> addStrings <| s + + let addBool (b: bool) (s: string) = + b |> BitConverter.GetBytes |> addBytes <| s + + let addDateTime (dt: System.DateTime) (s: string) = dt.Ticks.ToString() |> addString <| s + +module internal Md5Hasher = + + let private md5 = + new ThreadLocal<_>(fun () -> System.Security.Cryptography.MD5.Create()) + + let computeHash (bytes: byte array) = md5.Value.ComputeHash(bytes) + + let empty = Array.empty + + let hashString (s: string) = + s |> System.Text.Encoding.UTF8.GetBytes |> computeHash + + let addBytes (bytes: byte array) (s: byte array) = + + Array.append s bytes |> computeHash + + let addString (s: string) (s2: byte array) = + s |> System.Text.Encoding.UTF8.GetBytes |> addBytes <| s2 + + let addSeq<'item> (items: 'item seq) (addItem: 'item -> byte array -> byte array) (s: byte array) = + items |> Seq.fold (fun s a -> addItem a s) s + + let addStrings strings = addSeq strings addString + let addBytes' bytes = addSeq bytes addBytes + + // If we use this make it an extension method? + //let addVersions<'a, 'b when 'a :> ICacheKey<'b, string>> (versions: 'a seq) (s: string) = + // versions |> Seq.map (fun x -> x.GetVersion()) |> addStrings <| s + + let addBool (b: bool) (s: byte array) = + b |> BitConverter.GetBytes |> addBytes <| s + + let addDateTime (dt: System.DateTime) (s: byte array) = + dt.Ticks |> BitConverter.GetBytes |> addBytes <| s + + let addDateTimes (dts: System.DateTime seq) (s: byte array) = s |> addSeq dts addDateTime + + let toString (bytes: byte array) = bytes |> System.BitConverter.ToString diff --git a/src/Compiler/Facilities/Hashing.fsi b/src/Compiler/Facilities/Hashing.fsi new file mode 100644 index 00000000000..121afb29eb2 --- /dev/null +++ b/src/Compiler/Facilities/Hashing.fsi @@ -0,0 +1,46 @@ +namespace Internal.Utilities.Hashing + +/// Tools for hashing things with MD5 into a string that can be used as a cache key. +module internal Md5StringHasher = + + val hashString: s: string -> byte array + + val empty: string + + val addBytes: bytes: byte array -> s: string -> string + + val addString: s: string -> s2: string -> string + + val addSeq: items: 'item seq -> addItem: ('item -> string -> string) -> s: string -> string + + val addStrings: strings: string seq -> (string -> string) + + val addBool: b: bool -> s: string -> string + + val addDateTime: dt: System.DateTime -> s: string -> string + +module internal Md5Hasher = + + val computeHash: bytes: byte array -> byte array + + val empty: 'a array + + val hashString: s: string -> byte array + + val addBytes: bytes: byte array -> s: byte array -> byte array + + val addString: s: string -> s2: byte array -> byte array + + val addSeq: items: 'item seq -> addItem: ('item -> byte array -> byte array) -> s: byte array -> byte array + + val addStrings: strings: string seq -> (byte array -> byte array) + + val addBytes': bytes: byte array seq -> (byte array -> byte array) + + val addBool: b: bool -> s: byte array -> byte array + + val addDateTime: dt: System.DateTime -> s: byte array -> byte array + + val addDateTimes: dts: System.DateTime seq -> s: byte array -> byte array + + val toString: bytes: byte array -> string diff --git a/src/Compiler/Facilities/prim-lexing.fs b/src/Compiler/Facilities/prim-lexing.fs index 4aa1d3a79e5..6b927ef4a96 100644 --- a/src/Compiler/Facilities/prim-lexing.fs +++ b/src/Compiler/Facilities/prim-lexing.fs @@ -6,6 +6,11 @@ namespace FSharp.Compiler.Text open System open System.IO +open System.Collections.Immutable +open Internal.Utilities.Library + +open Internal.Utilities.Collections +open Internal.Utilities.Hashing type ISourceText = @@ -29,6 +34,11 @@ type ISourceText = abstract GetSubTextFromRange: range: range -> string +type ISourceTextNew = + inherit ISourceText + + abstract GetChecksum: unit -> System.Collections.Immutable.ImmutableArray + [] type StringText(str: string) = @@ -66,7 +76,7 @@ type StringText(str: string) = override _.ToString() = str - interface ISourceText with + interface ISourceTextNew with member _.Item with get index = str[index] @@ -97,7 +107,7 @@ type StringText(str: string) = if lastIndex <= startIndex || lastIndex >= str.Length then invalidArg "target" "Too big." - str.IndexOf(target, startIndex, target.Length) <> -1 + str.IndexOfOrdinal(target, startIndex, target.Length) <> -1 member _.Length = str.Length @@ -144,9 +154,45 @@ type StringText(str: string) = let lastLine = sourceText.GetLineString(range.EndLine - 1) sb.Append(lastLine.Substring(0, range.EndColumn)).ToString() + member _.GetChecksum() = + str |> Md5Hasher.hashString |> ImmutableArray.Create + module SourceText = let ofString str = StringText(str) :> ISourceText + +module SourceTextNew = + + let ofString str = StringText(str) :> ISourceTextNew + + let ofISourceText (sourceText: ISourceText) = + { new ISourceTextNew with + member _.Item + with get index = sourceText[index] + + member _.GetLineString(x) = sourceText.GetLineString(x) + + member _.GetLineCount() = sourceText.GetLineCount() + + member _.GetLastCharacterPosition() = sourceText.GetLastCharacterPosition() + + member _.GetSubTextString(x, y) = sourceText.GetSubTextString(x, y) + + member _.SubTextEquals(x, y) = sourceText.SubTextEquals(x, y) + + member _.Length = sourceText.Length + + member _.ContentEquals(x) = sourceText.ContentEquals(x) + + member _.CopyTo(a, b, c, d) = sourceText.CopyTo(a, b, c, d) + + member _.GetSubTextFromRange(x) = sourceText.GetSubTextFromRange(x) + + member _.GetChecksum() = + // TODO: something better... + sourceText.ToString() |> Md5Hasher.hashString |> ImmutableArray.Create + } + // NOTE: the code in this file is a drop-in replacement runtime for Lexing.fs from the FsLexYacc repository namespace Internal.Utilities.Text.Lexing diff --git a/src/Compiler/Facilities/prim-lexing.fsi b/src/Compiler/Facilities/prim-lexing.fsi index 6e5f6da4f25..ff13f96c9e1 100644 --- a/src/Compiler/Facilities/prim-lexing.fsi +++ b/src/Compiler/Facilities/prim-lexing.fsi @@ -39,12 +39,23 @@ type ISourceText = /// Throws an exception when the input range is outside the file boundaries. abstract GetSubTextFromRange: range: range -> string +/// Just like ISourceText, but with a checksum. Added as a separate type to avoid breaking changes. +type ISourceTextNew = + inherit ISourceText + + abstract GetChecksum: unit -> System.Collections.Immutable.ImmutableArray + /// Functions related to ISourceText objects module SourceText = /// Creates an ISourceText object from the given string val ofString: string -> ISourceText +module SourceTextNew = + + val ofString: string -> ISourceTextNew + val ofISourceText: ISourceText -> ISourceTextNew + // // NOTE: the code in this file is a drop-in replacement runtime for Lexing.fsi from the FsLexYacc repository // and is referenced by generated code for the three FsLex generated lexers in the F# compiler. diff --git a/src/Compiler/Interactive/fsi.fs b/src/Compiler/Interactive/fsi.fs index 040ad43e407..9ed34abfaac 100644 --- a/src/Compiler/Interactive/fsi.fs +++ b/src/Compiler/Interactive/fsi.fs @@ -933,12 +933,12 @@ type DiagnosticsLogger with /// Get the directory name from a string, with some defaults if it doesn't have one let internal directoryName (s: string) = - if s = "" then + if String.IsNullOrEmpty(s) then "." else match Path.GetDirectoryName s with | null -> if FileSystem.IsPathRootedShim s then s else "." - | res -> if res = "" then "." else res + | res -> if String.IsNullOrEmpty(res) then "." else res //---------------------------------------------------------------------------- // cmd line - state for options @@ -1526,7 +1526,7 @@ let ConvReflectionTypeToILTypeRef (reflectionTy: Type) = let scoref = ILScopeRef.Assembly aref let fullName = reflectionTy.FullName - let index = fullName.IndexOf("[") + let index = fullName.IndexOfOrdinal("[") let fullName = if index = -1 then @@ -4089,7 +4089,6 @@ type FsiInteractionProcessor ?cancellationToken: CancellationToken ) = let cancellationToken = defaultArg cancellationToken CancellationToken.None - use _ = Cancellable.UsingToken(cancellationToken) if tokenizer.LexBuffer.IsPastEndOfStream then let stepStatus = @@ -4218,7 +4217,6 @@ type FsiInteractionProcessor member _.EvalInteraction(ctok, sourceText, scriptFileName, diagnosticsLogger, ?cancellationToken) = let cancellationToken = defaultArg cancellationToken CancellationToken.None - use _ = Cancellable.UsingToken(cancellationToken) use _ = UseBuildPhase BuildPhase.Interactive use _ = UseDiagnosticsLogger diagnosticsLogger use _scope = SetCurrentUICultureForThread fsiOptions.FsiLCID @@ -4895,7 +4893,6 @@ type FsiEvaluationSession SpawnInteractiveServer(fsi, fsiOptions, fsiConsoleOutput) use _ = UseBuildPhase BuildPhase.Interactive - use _ = Cancellable.UsingToken(CancellationToken.None) if fsiOptions.Interact then // page in the type check env diff --git a/src/Compiler/Optimize/LowerStateMachines.fs b/src/Compiler/Optimize/LowerStateMachines.fs index 7c4835b3460..ef578e86064 100644 --- a/src/Compiler/Optimize/LowerStateMachines.fs +++ b/src/Compiler/Optimize/LowerStateMachines.fs @@ -114,7 +114,7 @@ let isExpandVar g (v: Val) = let isStateMachineBindingVar g (v: Val) = isExpandVar g v || (let nm = v.LogicalName - (nm.StartsWith "builder@" || v.IsMemberThisVal) && + (nm.StartsWithOrdinal("builder@") || v.IsMemberThisVal) && not v.IsCompiledAsTopLevel) type env = @@ -833,7 +833,7 @@ type LowerStateMachine(g: TcGlobals) = |> Result.Ok elif bind.Var.IsCompiledAsTopLevel || not (resBody.resumableVars.FreeLocals.Contains(bind.Var)) || - bind.Var.LogicalName.StartsWith stackVarPrefix then + bind.Var.LogicalName.StartsWithOrdinal(stackVarPrefix) then if sm_verbose then printfn "LetExpr (non-control-flow, rewrite rhs, RepresentBindingAsTopLevelOrLocal)" RepresentBindingAsTopLevelOrLocal bind resBody m |> Result.Ok diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index a1e01d4a58d..73ed2972ea0 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -230,20 +230,23 @@ type Summary<'Info> = // Note, this is a different notion of "size" to the one used for inlining heuristics //------------------------------------------------------------------------- -let rec SizeOfValueInfos (arr:_[]) = - if arr.Length <= 0 then 0 else max 0 (SizeOfValueInfo arr[0]) - -and SizeOfValueInfo x = - match x with - | SizeValue (vdepth, _v) -> vdepth // terminate recursion at CACHED size nodes - | ConstValue (_x, _) -> 1 - | UnknownValue -> 1 - | ValValue (_vr, vinfo) -> SizeOfValueInfo vinfo + 1 - | TupleValue vinfos - | RecdValue (_, vinfos) - | UnionCaseValue (_, vinfos) -> 1 + SizeOfValueInfos vinfos - | CurriedLambdaValue _ -> 1 - | ConstExprValue (_size, _) -> 1 +let SizeOfValueInfo valueInfo = + let rec loop acc valueInfo = + match valueInfo with + | SizeValue (vdepth, _v) -> assert (vdepth >= 0); acc + vdepth // terminate recursion at CACHED size nodes + | CurriedLambdaValue _ + | ConstExprValue _ + | ConstValue _ + | UnknownValue -> acc + 1 + | TupleValue vinfos + | RecdValue (_, vinfos) + | UnionCaseValue (_, vinfos) when vinfos.Length = 0 -> acc + 1 + | TupleValue vinfos + | RecdValue (_, vinfos) + | UnionCaseValue (_, vinfos) -> loop (acc + 1) vinfos[0] + | ValValue (_vr, vinfo) -> loop (acc + 1) vinfo + + loop 0 valueInfo let [] minDepthForASizeNode = 5 // for small vinfos do not record size info, save space @@ -1534,11 +1537,11 @@ let ValueOfExpr expr = let IsMutableStructuralBindingForTupleElement (vref: ValRef) = vref.IsCompilerGenerated && - vref.LogicalName.EndsWith suffixForTupleElementAssignmentTarget + vref.LogicalName.EndsWithOrdinal suffixForTupleElementAssignmentTarget let IsMutableForOutArg (vref: ValRef) = vref.IsCompilerGenerated && - vref.LogicalName.StartsWith(outArgCompilerGeneratedName) + vref.LogicalName.StartsWithOrdinal(outArgCompilerGeneratedName) let IsKnownOnlyMutableBeforeUse (vref: ValRef) = IsMutableStructuralBindingForTupleElement vref || @@ -1672,7 +1675,7 @@ let TryEliminateBinding cenv _env bind e2 _m = not vspec1.IsCompilerGenerated then None elif vspec1.IsFixed then None - elif vspec1.LogicalName.StartsWith stackVarPrefix || + elif vspec1.LogicalName.StartsWithOrdinal stackVarPrefix || vspec1.LogicalName.Contains suffixForVariablesThatMayNotBeEliminated then None else diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs new file mode 100644 index 00000000000..f9f952dde70 --- /dev/null +++ b/src/Compiler/Service/BackgroundCompiler.fs @@ -0,0 +1,1680 @@ +namespace FSharp.Compiler.CodeAnalysis + +open FSharp.Compiler.Text +open FSharp.Compiler.BuildGraph + +open System +open System.Diagnostics +open System.IO +open System.Reflection +open System.Reflection.Emit +open System.Threading +open Internal.Utilities.Collections +open Internal.Utilities.Library +open Internal.Utilities.Library.Extras +open FSharp.Compiler +open FSharp.Compiler.AbstractIL +open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.ILBinaryReader +open FSharp.Compiler.AbstractIL.ILDynamicAssemblyWriter +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.CompilerConfig +open FSharp.Compiler.CompilerDiagnostics +open FSharp.Compiler.CompilerImports +open FSharp.Compiler.CompilerOptions +open FSharp.Compiler.DependencyManager +open FSharp.Compiler.Diagnostics +open FSharp.Compiler.Driver +open FSharp.Compiler.DiagnosticsLogger +open FSharp.Compiler.IO +open FSharp.Compiler.ParseAndCheckInputs +open FSharp.Compiler.ScriptClosure +open FSharp.Compiler.Symbols +open FSharp.Compiler.Syntax +open FSharp.Compiler.Tokenization +open FSharp.Compiler.Text +open FSharp.Compiler.Text.Range +open FSharp.Compiler.TcGlobals +open FSharp.Compiler.BuildGraph +open FSharp.Compiler.CodeAnalysis.ProjectSnapshot + +type SourceTextHash = int64 +type CacheStamp = int64 +type FileName = string +type FilePath = string +type ProjectPath = string +type FileVersion = int + +type FSharpProjectSnapshot = FSharp.Compiler.CodeAnalysis.ProjectSnapshot.FSharpProjectSnapshot + +type internal IBackgroundCompiler = + + /// Type-check the result obtained by parsing. Force the evaluation of the antecedent type checking context if needed. + abstract member CheckFileInProject: + parseResults: FSharpParseFileResults * + fileName: string * + fileVersion: int * + sourceText: ISourceText * + options: FSharpProjectOptions * + userOpName: string -> + NodeCode + + /// Type-check the result obtained by parsing, but only if the antecedent type checking context is available. + abstract member CheckFileInProjectAllowingStaleCachedResults: + parseResults: FSharpParseFileResults * + fileName: string * + fileVersion: int * + sourceText: ISourceText * + options: FSharpProjectOptions * + userOpName: string -> + NodeCode + + abstract member ClearCache: options: seq * userOpName: string -> unit + + abstract member ClearCache: projects: ProjectSnapshot.FSharpProjectIdentifier seq * userOpName: string -> unit + + abstract member ClearCaches: unit -> unit + + abstract member DownsizeCaches: unit -> unit + + abstract member FindReferencesInFile: + fileName: string * + options: FSharpProjectOptions * + symbol: FSharp.Compiler.Symbols.FSharpSymbol * + canInvalidateProject: bool * + userOpName: string -> + NodeCode> + + abstract member FindReferencesInFile: + fileName: string * projectSnapshot: FSharpProjectSnapshot * symbol: FSharp.Compiler.Symbols.FSharpSymbol * userOpName: string -> + NodeCode> + + abstract member GetAssemblyData: + options: FSharpProjectOptions * outputFileName: string * userOpName: string -> + NodeCode + + abstract member GetAssemblyData: + projectSnapshot: FSharpProjectSnapshot * outputFileName: string * userOpName: string -> + NodeCode + + /// Fetch the check information from the background compiler (which checks w.r.t. the FileSystem API) + abstract member GetBackgroundCheckResultsForFileInProject: + fileName: string * options: FSharpProjectOptions * userOpName: string -> NodeCode + + /// Fetch the parse information from the background compiler (which checks w.r.t. the FileSystem API) + abstract member GetBackgroundParseResultsForFileInProject: + fileName: string * options: FSharpProjectOptions * userOpName: string -> NodeCode + + abstract member GetCachedCheckFileResult: + builder: IncrementalBuilder * fileName: string * sourceText: ISourceText * options: FSharpProjectOptions -> + NodeCode<(FSharpParseFileResults * FSharpCheckFileResults) option> + + abstract member GetProjectOptionsFromScript: + fileName: string * + sourceText: ISourceText * + previewEnabled: bool option * + loadedTimeStamp: System.DateTime option * + otherFlags: string array option * + useFsiAuxLib: bool option * + useSdkRefs: bool option * + sdkDirOverride: string option * + assumeDotNetFramework: bool option * + optionsStamp: int64 option * + userOpName: string -> + Async + + abstract member GetSemanticClassificationForFile: + fileName: string * options: FSharpProjectOptions * userOpName: string -> + NodeCode + + abstract member GetSemanticClassificationForFile: + fileName: string * snapshot: FSharpProjectSnapshot * userOpName: string -> + NodeCode + + abstract member InvalidateConfiguration: options: FSharpProjectOptions * userOpName: string -> unit + + abstract member NotifyFileChanged: fileName: string * options: FSharpProjectOptions * userOpName: string -> NodeCode + + abstract member NotifyProjectCleaned: options: FSharpProjectOptions * userOpName: string -> Async + + /// Parses and checks the source file and returns untyped AST and check results. + abstract member ParseAndCheckFileInProject: + fileName: string * fileVersion: int * sourceText: ISourceText * options: FSharpProjectOptions * userOpName: string -> + NodeCode + + abstract member ParseAndCheckFileInProject: + fileName: string * projectSnapshot: FSharpProjectSnapshot * userOpName: string -> + NodeCode + + /// Parse and typecheck the whole project. + abstract member ParseAndCheckProject: options: FSharpProjectOptions * userOpName: string -> NodeCode + + abstract member ParseAndCheckProject: projectSnapshot: FSharpProjectSnapshot * userOpName: string -> NodeCode + + abstract member ParseFile: + fileName: string * sourceText: ISourceText * options: FSharpParsingOptions * cache: bool * flatErrors: bool * userOpName: string -> + Async + + abstract member ParseFile: + fileName: string * projectSnapshot: FSharpProjectSnapshot * userOpName: string -> Async + + /// Try to get recent approximate type check results for a file. + abstract member TryGetRecentCheckResultsForFile: + fileName: string * options: FSharpProjectOptions * sourceText: ISourceText option * userOpName: string -> + (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option + + abstract member BeforeBackgroundFileCheck: IEvent + + abstract member FileChecked: IEvent + + abstract member FileParsed: IEvent + + abstract member FrameworkImportsCache: FrameworkImportsCache + + abstract member ProjectChecked: IEvent + +type internal ParseCacheLockToken() = + interface LockToken + +type CheckFileCacheKey = FileName * SourceTextHash * FSharpProjectOptions +type CheckFileCacheValue = FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash * DateTime + +[] +module internal EnvMisc = + let braceMatchCacheSize = GetEnvInteger "FCS_BraceMatchCacheSize" 5 + let parseFileCacheSize = GetEnvInteger "FCS_ParseFileCacheSize" 2 + let checkFileInProjectCacheSize = GetEnvInteger "FCS_CheckFileInProjectCacheSize" 10 + + let projectCacheSizeDefault = GetEnvInteger "FCS_ProjectCacheSizeDefault" 3 + + let frameworkTcImportsCacheStrongSize = + GetEnvInteger "FCS_frameworkTcImportsCacheStrongSizeDefault" 8 + +[] +module internal Helpers = + + /// Determine whether two (fileName,options) keys are identical w.r.t. affect on checking + let AreSameForChecking2 ((fileName1: string, options1: FSharpProjectOptions), (fileName2, options2)) = + (fileName1 = fileName2) + && FSharpProjectOptions.AreSameForChecking(options1, options2) + + /// Determine whether two (fileName,options) keys should be identical w.r.t. resource usage + let AreSubsumable2 ((fileName1: string, o1: FSharpProjectOptions), (fileName2: string, o2: FSharpProjectOptions)) = + (fileName1 = fileName2) && FSharpProjectOptions.UseSameProject(o1, o2) + + /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. parsing + let AreSameForParsing ((fileName1: string, source1Hash: int64, options1), (fileName2, source2Hash, options2)) = + fileName1 = fileName2 && options1 = options2 && source1Hash = source2Hash + + let AreSimilarForParsing ((fileName1, _, _), (fileName2, _, _)) = fileName1 = fileName2 + + /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. checking + let AreSameForChecking3 ((fileName1: string, source1Hash: int64, options1: FSharpProjectOptions), (fileName2, source2Hash, options2)) = + (fileName1 = fileName2) + && FSharpProjectOptions.AreSameForChecking(options1, options2) + && source1Hash = source2Hash + + /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. resource usage + let AreSubsumable3 ((fileName1: string, _, o1: FSharpProjectOptions), (fileName2: string, _, o2: FSharpProjectOptions)) = + (fileName1 = fileName2) && FSharpProjectOptions.UseSameProject(o1, o2) + + /// If a symbol is an attribute check if given set of names contains its name without the Attribute suffix + let rec NamesContainAttribute (symbol: FSharpSymbol) names = + match symbol with + | :? FSharpMemberOrFunctionOrValue as mofov -> + mofov.DeclaringEntity + |> Option.map (fun entity -> NamesContainAttribute entity names) + |> Option.defaultValue false + | :? FSharpEntity as entity when entity.IsAttributeType && symbol.DisplayNameCore.EndsWithOrdinal "Attribute" -> + let nameWithoutAttribute = String.dropSuffix symbol.DisplayNameCore "Attribute" + names |> Set.contains nameWithoutAttribute + | _ -> false + +// There is only one instance of this type, held in FSharpChecker +type internal BackgroundCompiler + ( + legacyReferenceResolver, + projectCacheSize, + keepAssemblyContents, + keepAllBackgroundResolutions, + tryGetMetadataSnapshot, + suggestNamesForErrors, + keepAllBackgroundSymbolUses, + enableBackgroundItemKeyStoreAndSemanticClassification, + enablePartialTypeChecking, + parallelReferenceResolution, + captureIdentifiersWhenParsing, + getSource: (string -> Async) option, + useChangeNotifications, + useSyntaxTreeCache + ) as self = + + let beforeFileChecked = Event() + let fileParsed = Event() + let fileChecked = Event() + let projectChecked = Event() + + // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.backgroundCompiler.scriptClosureCache + /// Information about the derived script closure. + let scriptClosureCache = + MruCache( + projectCacheSize, + areSame = FSharpProjectOptions.AreSameForChecking, + areSimilar = FSharpProjectOptions.UseSameProject + ) + + let frameworkTcImportsCache = + FrameworkImportsCache(frameworkTcImportsCacheStrongSize) + + // We currently share one global dependency provider for all scripts for the FSharpChecker. + // For projects, one is used per project. + // + // Sharing one for all scripts is necessary for good performance from GetProjectOptionsFromScript, + // which requires a dependency provider to process through the project options prior to working out + // if the cached incremental builder can be used for the project. + let dependencyProviderForScripts = new DependencyProvider() + + let getProjectReferences (options: FSharpProjectOptions) userOpName = + [ + for r in options.ReferencedProjects do + + match r with + | FSharpReferencedProject.FSharpReference(nm, opts) -> + // Don't use cross-project references for FSharp.Core, since various bits of code + // require a concrete FSharp.Core to exist on-disk. The only solutions that have + // these cross-project references to FSharp.Core are VisualFSharp.sln and FSharp.sln. The ramification + // of this is that you need to build FSharp.Core to get intellisense in those projects. + + if + (try + Path.GetFileNameWithoutExtension(nm) + with _ -> + "") + <> GetFSharpCoreLibraryName() + then + { new IProjectReference with + member x.EvaluateRawContents() = + node { + Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "GetAssemblyData", nm) + return! self.GetAssemblyData(opts, userOpName + ".CheckReferencedProject(" + nm + ")") + } + + member x.TryGetLogicalTimeStamp(cache) = + self.TryGetLogicalTimeStampForProject(cache, opts) + + member x.FileName = nm + } + + | FSharpReferencedProject.PEReference(getStamp, delayedReader) -> + { new IProjectReference with + member x.EvaluateRawContents() = + node { + let! ilReaderOpt = delayedReader.TryGetILModuleReader() |> NodeCode.FromCancellable + + match ilReaderOpt with + | Some ilReader -> + let ilModuleDef, ilAsmRefs = ilReader.ILModuleDef, ilReader.ILAssemblyRefs + let data = RawFSharpAssemblyData(ilModuleDef, ilAsmRefs) :> IRawFSharpAssemblyData + return ProjectAssemblyDataResult.Available data + | _ -> + // Note 'false' - if a PEReference doesn't find an ILModuleReader then we don't + // continue to try to use an on-disk DLL + return ProjectAssemblyDataResult.Unavailable false + } + + member x.TryGetLogicalTimeStamp _ = getStamp () |> Some + member x.FileName = delayedReader.OutputFile + } + + | FSharpReferencedProject.ILModuleReference(nm, getStamp, getReader) -> + { new IProjectReference with + member x.EvaluateRawContents() = + cancellable { + let ilReader = getReader () + let ilModuleDef, ilAsmRefs = ilReader.ILModuleDef, ilReader.ILAssemblyRefs + let data = RawFSharpAssemblyData(ilModuleDef, ilAsmRefs) :> IRawFSharpAssemblyData + return ProjectAssemblyDataResult.Available data + } + |> NodeCode.FromCancellable + + member x.TryGetLogicalTimeStamp _ = getStamp () |> Some + member x.FileName = nm + } + ] + + /// CreateOneIncrementalBuilder (for background type checking). Note that fsc.fs also + /// creates an incremental builder used by the command line compiler. + let CreateOneIncrementalBuilder (options: FSharpProjectOptions, userOpName) = + node { + use _ = + Activity.start "BackgroundCompiler.CreateOneIncrementalBuilder" [| Activity.Tags.project, options.ProjectFileName |] + + Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "CreateOneIncrementalBuilder", options.ProjectFileName) + let projectReferences = getProjectReferences options userOpName + + let loadClosure = scriptClosureCache.TryGet(AnyCallerThread, options) + + let dependencyProvider = + if options.UseScriptResolutionRules then + Some dependencyProviderForScripts + else + None + + let! builderOpt, diagnostics = + IncrementalBuilder.TryCreateIncrementalBuilderForProjectOptions( + legacyReferenceResolver, + FSharpCheckerResultsSettings.defaultFSharpBinariesDir, + frameworkTcImportsCache, + loadClosure, + Array.toList options.SourceFiles, + Array.toList options.OtherOptions, + projectReferences, + options.ProjectDirectory, + options.UseScriptResolutionRules, + keepAssemblyContents, + keepAllBackgroundResolutions, + tryGetMetadataSnapshot, + suggestNamesForErrors, + keepAllBackgroundSymbolUses, + enableBackgroundItemKeyStoreAndSemanticClassification, + enablePartialTypeChecking, + dependencyProvider, + parallelReferenceResolution, + captureIdentifiersWhenParsing, + getSource, + useChangeNotifications, + useSyntaxTreeCache + ) + + match builderOpt with + | None -> () + | Some builder -> + +#if !NO_TYPEPROVIDERS + // Register the behaviour that responds to CCUs being invalidated because of type + // provider Invalidate events. This invalidates the configuration in the build. + builder.ImportsInvalidatedByTypeProvider.Add(fun () -> self.InvalidateConfiguration(options, userOpName)) +#endif + + // Register the callback called just before a file is typechecked by the background builder (without recording + // errors or intellisense information). + // + // This indicates to the UI that the file type check state is dirty. If the file is open and visible then + // the UI will sooner or later request a typecheck of the file, recording errors and intellisense information. + builder.BeforeFileChecked.Add(fun file -> beforeFileChecked.Trigger(file, options)) + builder.FileParsed.Add(fun file -> fileParsed.Trigger(file, options)) + builder.FileChecked.Add(fun file -> fileChecked.Trigger(file, options)) + builder.ProjectChecked.Add(fun () -> projectChecked.Trigger options) + + return (builderOpt, diagnostics) + } + + let parseCacheLock = Lock() + + // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.parseFileInProjectCache. Most recently used cache for parsing files. + let parseFileCache = + MruCache( + parseFileCacheSize, + areSimilar = AreSimilarForParsing, + areSame = AreSameForParsing + ) + + // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.checkFileInProjectCache + // + /// Cache which holds recently seen type-checks. + /// This cache may hold out-of-date entries, in two senses + /// - there may be a more recent antecedent state available because the background build has made it available + /// - the source for the file may have changed + + // Also keyed on source. This can only be out of date if the antecedent is out of date + let checkFileInProjectCache = + MruCache>( + keepStrongly = checkFileInProjectCacheSize, + areSame = AreSameForChecking3, + areSimilar = AreSubsumable3 + ) + + // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.backgroundCompiler.incrementalBuildersCache. This root typically holds more + // live information than anything else in the F# Language Service, since it holds up to 3 (projectCacheStrongSize) background project builds + // strongly. + // + /// Cache of builds keyed by options. + let gate = obj () + + let incrementalBuildersCache = + MruCache>( + keepStrongly = projectCacheSize, + keepMax = projectCacheSize, + areSame = FSharpProjectOptions.AreSameForChecking, + areSimilar = FSharpProjectOptions.UseSameProject + ) + + let tryGetBuilderNode options = + incrementalBuildersCache.TryGet(AnyCallerThread, options) + + let tryGetBuilder options : NodeCode option = + tryGetBuilderNode options |> Option.map (fun x -> x.GetOrComputeValue()) + + let tryGetSimilarBuilder options : NodeCode option = + incrementalBuildersCache.TryGetSimilar(AnyCallerThread, options) + |> Option.map (fun x -> x.GetOrComputeValue()) + + let tryGetAnyBuilder options : NodeCode option = + incrementalBuildersCache.TryGetAny(AnyCallerThread, options) + |> Option.map (fun x -> x.GetOrComputeValue()) + + let createBuilderNode (options, userOpName, ct: CancellationToken) = + lock gate (fun () -> + if ct.IsCancellationRequested then + GraphNode.FromResult(None, [||]) + else + let getBuilderNode = GraphNode(CreateOneIncrementalBuilder(options, userOpName)) + incrementalBuildersCache.Set(AnyCallerThread, options, getBuilderNode) + getBuilderNode) + + let createAndGetBuilder (options, userOpName) = + node { + let! ct = NodeCode.CancellationToken + let getBuilderNode = createBuilderNode (options, userOpName, ct) + return! getBuilderNode.GetOrComputeValue() + } + + let getOrCreateBuilder (options, userOpName) : NodeCode = + match tryGetBuilder options with + | Some getBuilder -> + node { + match! getBuilder with + | builderOpt, creationDiags when builderOpt.IsNone || not builderOpt.Value.IsReferencesInvalidated -> + return builderOpt, creationDiags + | _ -> + // The builder could be re-created, + // clear the check file caches that are associated with it. + // We must do this in order to not return stale results when references + // in the project get changed/added/removed. + parseCacheLock.AcquireLock(fun ltok -> + options.SourceFiles + |> Array.iter (fun sourceFile -> + let key = (sourceFile, 0L, options) + checkFileInProjectCache.RemoveAnySimilar(ltok, key))) + + return! createAndGetBuilder (options, userOpName) + } + | _ -> createAndGetBuilder (options, userOpName) + + let getSimilarOrCreateBuilder (options, userOpName) = + match tryGetSimilarBuilder options with + | Some res -> res + // The builder does not exist at all. Create it. + | None -> getOrCreateBuilder (options, userOpName) + + let getOrCreateBuilderWithInvalidationFlag (options, canInvalidateProject, userOpName) = + if canInvalidateProject then + getOrCreateBuilder (options, userOpName) + else + getSimilarOrCreateBuilder (options, userOpName) + + let getAnyBuilder (options, userOpName) = + match tryGetAnyBuilder options with + | Some getBuilder -> getBuilder + | _ -> getOrCreateBuilder (options, userOpName) + + static let mutable actualParseFileCount = 0 + + static let mutable actualCheckFileCount = 0 + + /// Should be a fast operation. Ensures that we have only one async lazy object per file and its hash. + let getCheckFileNode (parseResults, sourceText, fileName, options, _fileVersion, builder, tcPrior, tcInfo, creationDiags) = + + // Here we lock for the creation of the node, not its execution + parseCacheLock.AcquireLock(fun ltok -> + let key = (fileName, sourceText.GetHashCode() |> int64, options) + + match checkFileInProjectCache.TryGet(ltok, key) with + | Some res -> res + | _ -> + let res = + GraphNode( + node { + let! res = + self.CheckOneFileImplAux( + parseResults, + sourceText, + fileName, + options, + builder, + tcPrior, + tcInfo, + creationDiags + ) + + Interlocked.Increment(&actualCheckFileCount) |> ignore + return res + } + ) + + checkFileInProjectCache.Set(ltok, key, res) + res) + + member _.ParseFile + ( + fileName: string, + sourceText: ISourceText, + options: FSharpParsingOptions, + cache: bool, + flatErrors: bool, + userOpName: string + ) = + async { + use _ = + Activity.start + "BackgroundCompiler.ParseFile" + [| + Activity.Tags.fileName, fileName + Activity.Tags.userOpName, userOpName + Activity.Tags.cache, cache.ToString() + |] + + if cache then + let hash = sourceText.GetHashCode() |> int64 + + match parseCacheLock.AcquireLock(fun ltok -> parseFileCache.TryGet(ltok, (fileName, hash, options))) with + | Some res -> return res + | None -> + Interlocked.Increment(&actualParseFileCount) |> ignore + let! ct = Async.CancellationToken + + let parseDiagnostics, parseTree, anyErrors = + ParseAndCheckFile.parseFile ( + sourceText, + fileName, + options, + userOpName, + suggestNamesForErrors, + flatErrors, + captureIdentifiersWhenParsing, + ct + ) + + let res = + FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, options.SourceFiles) + + parseCacheLock.AcquireLock(fun ltok -> parseFileCache.Set(ltok, (fileName, hash, options), res)) + return res + else + let! ct = Async.CancellationToken + + let parseDiagnostics, parseTree, anyErrors = + ParseAndCheckFile.parseFile ( + sourceText, + fileName, + options, + userOpName, + false, + flatErrors, + captureIdentifiersWhenParsing, + ct + ) + + return FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, options.SourceFiles) + } + + /// Fetch the parse information from the background compiler (which checks w.r.t. the FileSystem API) + member _.GetBackgroundParseResultsForFileInProject(fileName, options, userOpName) = + node { + use _ = + Activity.start + "BackgroundCompiler.GetBackgroundParseResultsForFileInProject" + [| Activity.Tags.fileName, fileName; Activity.Tags.userOpName, userOpName |] + + let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName) + + match builderOpt with + | None -> + let parseTree = EmptyParsedInput(fileName, (false, false)) + return FSharpParseFileResults(creationDiags, parseTree, true, [||]) + | Some builder -> + let parseTree, _, _, parseDiagnostics = builder.GetParseResultsForFile fileName + + let parseDiagnostics = + DiagnosticHelpers.CreateDiagnostics( + builder.TcConfig.diagnosticsOptions, + false, + fileName, + parseDiagnostics, + suggestNamesForErrors, + builder.TcConfig.flatErrors, + None + ) + + let diagnostics = [| yield! creationDiags; yield! parseDiagnostics |] + + let parseResults = + FSharpParseFileResults( + diagnostics = diagnostics, + input = parseTree, + parseHadErrors = false, + dependencyFiles = builder.AllDependenciesDeprecated + ) + + return parseResults + } + + member _.GetCachedCheckFileResult(builder: IncrementalBuilder, fileName, sourceText: ISourceText, options) = + node { + use _ = + Activity.start "BackgroundCompiler.GetCachedCheckFileResult" [| Activity.Tags.fileName, fileName |] + + let hash = sourceText.GetHashCode() |> int64 + let key = (fileName, hash, options) + + let cachedResultsOpt = + parseCacheLock.AcquireLock(fun ltok -> checkFileInProjectCache.TryGet(ltok, key)) + + match cachedResultsOpt with + | Some cachedResults -> + match! cachedResults.GetOrComputeValue() with + | parseResults, checkResults, _, priorTimeStamp when + (match builder.GetCheckResultsBeforeFileInProjectEvenIfStale fileName with + | None -> false + | Some(tcPrior) -> + tcPrior.ProjectTimeStamp = priorTimeStamp + && builder.AreCheckResultsBeforeFileInProjectReady(fileName)) + -> + return Some(parseResults, checkResults) + | _ -> + parseCacheLock.AcquireLock(fun ltok -> checkFileInProjectCache.RemoveAnySimilar(ltok, key)) + return None + | _ -> return None + } + + member private _.CheckOneFileImplAux + ( + parseResults: FSharpParseFileResults, + sourceText: ISourceText, + fileName: string, + options: FSharpProjectOptions, + builder: IncrementalBuilder, + tcPrior: PartialCheckResults, + tcInfo: TcInfo, + creationDiags: FSharpDiagnostic[] + ) : NodeCode = + + node { + // Get additional script #load closure information if applicable. + // For scripts, this will have been recorded by GetProjectOptionsFromScript. + let tcConfig = tcPrior.TcConfig + let loadClosure = scriptClosureCache.TryGet(AnyCallerThread, options) + + let! checkAnswer = + FSharpCheckFileResults.CheckOneFile( + parseResults, + sourceText, + fileName, + options.ProjectFileName, + tcConfig, + tcPrior.TcGlobals, + tcPrior.TcImports, + tcInfo.tcState, + tcInfo.moduleNamesDict, + loadClosure, + tcInfo.TcDiagnostics, + options.IsIncompleteTypeCheckEnvironment, + options, + Some builder, + Array.ofList tcInfo.tcDependencyFiles, + creationDiags, + parseResults.Diagnostics, + keepAssemblyContents, + suggestNamesForErrors + ) + |> NodeCode.FromCancellable + + GraphNode.SetPreferredUILang tcConfig.preferredUiLang + return (parseResults, checkAnswer, sourceText.GetHashCode() |> int64, tcPrior.ProjectTimeStamp) + } + + member private bc.CheckOneFileImpl + ( + parseResults: FSharpParseFileResults, + sourceText: ISourceText, + fileName: string, + options: FSharpProjectOptions, + fileVersion: int, + builder: IncrementalBuilder, + tcPrior: PartialCheckResults, + tcInfo: TcInfo, + creationDiags: FSharpDiagnostic[] + ) = + + node { + match! bc.GetCachedCheckFileResult(builder, fileName, sourceText, options) with + | Some(_, results) -> return FSharpCheckFileAnswer.Succeeded results + | _ -> + let lazyCheckFile = + getCheckFileNode (parseResults, sourceText, fileName, options, fileVersion, builder, tcPrior, tcInfo, creationDiags) + + let! _, results, _, _ = lazyCheckFile.GetOrComputeValue() + return FSharpCheckFileAnswer.Succeeded results + } + + /// Type-check the result obtained by parsing, but only if the antecedent type checking context is available. + member bc.CheckFileInProjectAllowingStaleCachedResults + ( + parseResults: FSharpParseFileResults, + fileName, + fileVersion, + sourceText: ISourceText, + options, + userOpName + ) = + node { + use _ = + Activity.start + "BackgroundCompiler.CheckFileInProjectAllowingStaleCachedResults" + [| + Activity.Tags.project, options.ProjectFileName + Activity.Tags.fileName, fileName + Activity.Tags.userOpName, userOpName + |] + + let! cachedResults = + node { + let! builderOpt, creationDiags = getAnyBuilder (options, userOpName) + + match builderOpt with + | Some builder -> + match! bc.GetCachedCheckFileResult(builder, fileName, sourceText, options) with + | Some(_, checkResults) -> return Some(builder, creationDiags, Some(FSharpCheckFileAnswer.Succeeded checkResults)) + | _ -> return Some(builder, creationDiags, None) + | _ -> return None // the builder wasn't ready + } + + match cachedResults with + | None -> return None + | Some(_, _, Some x) -> return Some x + | Some(builder, creationDiags, None) -> + Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "CheckFileInProjectAllowingStaleCachedResults.CacheMiss", fileName) + + match builder.GetCheckResultsBeforeFileInProjectEvenIfStale fileName with + | Some tcPrior -> + match tcPrior.TryPeekTcInfo() with + | Some tcInfo -> + let! checkResults = + bc.CheckOneFileImpl( + parseResults, + sourceText, + fileName, + options, + fileVersion, + builder, + tcPrior, + tcInfo, + creationDiags + ) + + return Some checkResults + | None -> return None + | None -> return None // the incremental builder was not up to date + } + + /// Type-check the result obtained by parsing. Force the evaluation of the antecedent type checking context if needed. + member bc.CheckFileInProject + ( + parseResults: FSharpParseFileResults, + fileName, + fileVersion, + sourceText: ISourceText, + options, + userOpName + ) = + node { + use _ = + Activity.start + "BackgroundCompiler.CheckFileInProject" + [| + Activity.Tags.project, options.ProjectFileName + Activity.Tags.fileName, fileName + Activity.Tags.userOpName, userOpName + |] + + let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName) + + match builderOpt with + | None -> + return FSharpCheckFileAnswer.Succeeded(FSharpCheckFileResults.MakeEmpty(fileName, creationDiags, keepAssemblyContents)) + | Some builder -> + // Check the cache. We can only use cached results when there is no work to do to bring the background builder up-to-date + let! cachedResults = bc.GetCachedCheckFileResult(builder, fileName, sourceText, options) + + match cachedResults with + | Some(_, checkResults) -> return FSharpCheckFileAnswer.Succeeded checkResults + | _ -> + let! tcPrior = builder.GetCheckResultsBeforeFileInProject fileName + let! tcInfo = tcPrior.GetOrComputeTcInfo() + + return! + bc.CheckOneFileImpl( + parseResults, + sourceText, + fileName, + options, + fileVersion, + builder, + tcPrior, + tcInfo, + creationDiags + ) + } + + /// Parses and checks the source file and returns untyped AST and check results. + member bc.ParseAndCheckFileInProject + ( + fileName: string, + fileVersion, + sourceText: ISourceText, + options: FSharpProjectOptions, + userOpName + ) = + node { + use _ = + Activity.start + "BackgroundCompiler.ParseAndCheckFileInProject" + [| + Activity.Tags.project, options.ProjectFileName + Activity.Tags.fileName, fileName + Activity.Tags.userOpName, userOpName + |] + + let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName) + + match builderOpt with + | None -> + let parseTree = EmptyParsedInput(fileName, (false, false)) + let parseResults = FSharpParseFileResults(creationDiags, parseTree, true, [||]) + return (parseResults, FSharpCheckFileAnswer.Aborted) + + | Some builder -> + let! cachedResults = bc.GetCachedCheckFileResult(builder, fileName, sourceText, options) + + match cachedResults with + | Some(parseResults, checkResults) -> return (parseResults, FSharpCheckFileAnswer.Succeeded checkResults) + | _ -> + let! tcPrior = builder.GetCheckResultsBeforeFileInProject fileName + let! tcInfo = tcPrior.GetOrComputeTcInfo() + // Do the parsing. + let parsingOptions = + FSharpParsingOptions.FromTcConfig( + builder.TcConfig, + Array.ofList builder.SourceFiles, + options.UseScriptResolutionRules + ) + + GraphNode.SetPreferredUILang tcPrior.TcConfig.preferredUiLang + let! ct = NodeCode.CancellationToken + + let parseDiagnostics, parseTree, anyErrors = + ParseAndCheckFile.parseFile ( + sourceText, + fileName, + parsingOptions, + userOpName, + suggestNamesForErrors, + builder.TcConfig.flatErrors, + captureIdentifiersWhenParsing, + ct + ) + + let parseResults = + FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, builder.AllDependenciesDeprecated) + + let! checkResults = + bc.CheckOneFileImpl( + parseResults, + sourceText, + fileName, + options, + fileVersion, + builder, + tcPrior, + tcInfo, + creationDiags + ) + + return (parseResults, checkResults) + } + + member _.NotifyFileChanged(fileName, options, userOpName) = + node { + use _ = + Activity.start + "BackgroundCompiler.NotifyFileChanged" + [| + Activity.Tags.project, options.ProjectFileName + Activity.Tags.fileName, fileName + Activity.Tags.userOpName, userOpName + |] + + let! builderOpt, _ = getOrCreateBuilder (options, userOpName) + + match builderOpt with + | None -> return () + | Some builder -> do! builder.NotifyFileChanged(fileName, DateTime.UtcNow) + } + + /// Fetch the check information from the background compiler (which checks w.r.t. the FileSystem API) + member _.GetBackgroundCheckResultsForFileInProject(fileName, options, userOpName) = + node { + use _ = + Activity.start + "BackgroundCompiler.ParseAndCheckFileInProject" + [| + Activity.Tags.project, options.ProjectFileName + Activity.Tags.fileName, fileName + Activity.Tags.userOpName, userOpName + |] + + let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName) + + match builderOpt with + | None -> + let parseTree = EmptyParsedInput(fileName, (false, false)) + let parseResults = FSharpParseFileResults(creationDiags, parseTree, true, [||]) + let typedResults = FSharpCheckFileResults.MakeEmpty(fileName, creationDiags, true) + return (parseResults, typedResults) + | Some builder -> + let parseTree, _, _, parseDiagnostics = builder.GetParseResultsForFile fileName + let! tcProj = builder.GetFullCheckResultsAfterFileInProject fileName + + let! tcInfo, tcInfoExtras = tcProj.GetOrComputeTcInfoWithExtras() + + let tcResolutions = tcInfoExtras.tcResolutions + let tcSymbolUses = tcInfoExtras.tcSymbolUses + let tcOpenDeclarations = tcInfoExtras.tcOpenDeclarations + let latestCcuSigForFile = tcInfo.latestCcuSigForFile + let tcState = tcInfo.tcState + let tcEnvAtEnd = tcInfo.tcEnvAtEndOfFile + let latestImplementationFile = tcInfoExtras.latestImplFile + let tcDependencyFiles = tcInfo.tcDependencyFiles + let tcDiagnostics = tcInfo.TcDiagnostics + let diagnosticsOptions = builder.TcConfig.diagnosticsOptions + + let symbolEnv = + SymbolEnv(tcProj.TcGlobals, tcInfo.tcState.Ccu, Some tcInfo.tcState.CcuSig, tcProj.TcImports) + |> Some + + let parseDiagnostics = + DiagnosticHelpers.CreateDiagnostics( + diagnosticsOptions, + false, + fileName, + parseDiagnostics, + suggestNamesForErrors, + builder.TcConfig.flatErrors, + None + ) + + let parseDiagnostics = [| yield! creationDiags; yield! parseDiagnostics |] + + let tcDiagnostics = + DiagnosticHelpers.CreateDiagnostics( + diagnosticsOptions, + false, + fileName, + tcDiagnostics, + suggestNamesForErrors, + builder.TcConfig.flatErrors, + symbolEnv + ) + + let tcDiagnostics = [| yield! creationDiags; yield! tcDiagnostics |] + + let parseResults = + FSharpParseFileResults( + diagnostics = parseDiagnostics, + input = parseTree, + parseHadErrors = false, + dependencyFiles = builder.AllDependenciesDeprecated + ) + + let loadClosure = scriptClosureCache.TryGet(AnyCallerThread, options) + + let typedResults = + FSharpCheckFileResults.Make( + fileName, + options.ProjectFileName, + tcProj.TcConfig, + tcProj.TcGlobals, + options.IsIncompleteTypeCheckEnvironment, + Some builder, + options, + Array.ofList tcDependencyFiles, + creationDiags, + parseResults.Diagnostics, + tcDiagnostics, + keepAssemblyContents, + Option.get latestCcuSigForFile, + tcState.Ccu, + tcProj.TcImports, + tcEnvAtEnd.AccessRights, + tcResolutions, + tcSymbolUses, + tcEnvAtEnd.NameEnv, + loadClosure, + latestImplementationFile, + tcOpenDeclarations + ) + + return (parseResults, typedResults) + } + + member _.FindReferencesInFile + ( + fileName: string, + options: FSharpProjectOptions, + symbol: FSharpSymbol, + canInvalidateProject: bool, + userOpName: string + ) = + node { + use _ = + Activity.start + "BackgroundCompiler.FindReferencesInFile" + [| + Activity.Tags.project, options.ProjectFileName + Activity.Tags.fileName, fileName + Activity.Tags.userOpName, userOpName + "symbol", symbol.FullName + |] + + let! builderOpt, _ = getOrCreateBuilderWithInvalidationFlag (options, canInvalidateProject, userOpName) + + match builderOpt with + | None -> return Seq.empty + | Some builder -> + if builder.ContainsFile fileName then + let! checkResults = builder.GetFullCheckResultsAfterFileInProject fileName + let! keyStoreOpt = checkResults.GetOrComputeItemKeyStoreIfEnabled() + + match keyStoreOpt with + | None -> return Seq.empty + | Some reader -> return reader.FindAll symbol.Item + else + return Seq.empty + } + + member _.GetSemanticClassificationForFile(fileName: string, options: FSharpProjectOptions, userOpName: string) = + node { + use _ = + Activity.start + "BackgroundCompiler.GetSemanticClassificationForFile" + [| + Activity.Tags.project, options.ProjectFileName + Activity.Tags.fileName, fileName + Activity.Tags.userOpName, userOpName + |] + + let! builderOpt, _ = getOrCreateBuilder (options, userOpName) + + match builderOpt with + | None -> return None + | Some builder -> + let! checkResults = builder.GetFullCheckResultsAfterFileInProject fileName + let! scopt = checkResults.GetOrComputeSemanticClassificationIfEnabled() + + match scopt with + | None -> return None + | Some sc -> return Some(sc.GetView()) + } + + /// Try to get recent approximate type check results for a file. + member _.TryGetRecentCheckResultsForFile + ( + fileName: string, + options: FSharpProjectOptions, + sourceText: ISourceText option, + _userOpName: string + ) = + use _ = + Activity.start + "BackgroundCompiler.GetSemanticClassificationForFile" + [| + Activity.Tags.project, options.ProjectFileName + Activity.Tags.fileName, fileName + Activity.Tags.userOpName, _userOpName + |] + + match sourceText with + | Some sourceText -> + let hash = sourceText.GetHashCode() |> int64 + + let resOpt = + parseCacheLock.AcquireLock(fun ltok -> checkFileInProjectCache.TryGet(ltok, (fileName, hash, options))) + + match resOpt with + | Some res -> + match res.TryPeekValue() with + | ValueSome(a, b, c, _) -> Some(a, b, c) + | ValueNone -> None + | None -> None + | None -> None + + /// Parse and typecheck the whole project (the implementation, called recursively as project graph is evaluated) + member private _.ParseAndCheckProjectImpl(options, userOpName) = + node { + + let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName) + + match builderOpt with + | None -> + let emptyResults = + FSharpCheckProjectResults(options.ProjectFileName, None, keepAssemblyContents, creationDiags, None) + + return emptyResults + | Some builder -> + let! tcProj, ilAssemRef, tcAssemblyDataOpt, tcAssemblyExprOpt = builder.GetFullCheckResultsAndImplementationsForProject() + let diagnosticsOptions = tcProj.TcConfig.diagnosticsOptions + let fileName = DummyFileNameForRangesWithoutASpecificLocation + + // Although we do not use 'tcInfoExtras', computing it will make sure we get an extra info. + let! tcInfo, _tcInfoExtras = tcProj.GetOrComputeTcInfoWithExtras() + + let topAttribs = tcInfo.topAttribs + let tcState = tcInfo.tcState + let tcEnvAtEnd = tcInfo.tcEnvAtEndOfFile + let tcDiagnostics = tcInfo.TcDiagnostics + let tcDependencyFiles = tcInfo.tcDependencyFiles + + let symbolEnv = + SymbolEnv(tcProj.TcGlobals, tcInfo.tcState.Ccu, Some tcInfo.tcState.CcuSig, tcProj.TcImports) + |> Some + + let tcDiagnostics = + DiagnosticHelpers.CreateDiagnostics( + diagnosticsOptions, + true, + fileName, + tcDiagnostics, + suggestNamesForErrors, + builder.TcConfig.flatErrors, + symbolEnv + ) + + let diagnostics = [| yield! creationDiags; yield! tcDiagnostics |] + + let getAssemblyData () = + match tcAssemblyDataOpt with + | ProjectAssemblyDataResult.Available data -> Some data + | _ -> None + + let details = + (tcProj.TcGlobals, + tcProj.TcImports, + tcState.Ccu, + tcState.CcuSig, + Choice1Of2 builder, + topAttribs, + getAssemblyData, + ilAssemRef, + tcEnvAtEnd.AccessRights, + tcAssemblyExprOpt, + Array.ofList tcDependencyFiles, + options) + + let results = + FSharpCheckProjectResults( + options.ProjectFileName, + Some tcProj.TcConfig, + keepAssemblyContents, + diagnostics, + Some details + ) + + return results + } + + member _.GetAssemblyData(options, userOpName) = + node { + use _ = + Activity.start + "BackgroundCompiler.GetAssemblyData" + [| + Activity.Tags.project, options.ProjectFileName + Activity.Tags.userOpName, userOpName + |] + + let! builderOpt, _ = getOrCreateBuilder (options, userOpName) + + match builderOpt with + | None -> return ProjectAssemblyDataResult.Unavailable true + | Some builder -> + let! _, _, tcAssemblyDataOpt, _ = builder.GetCheckResultsAndImplementationsForProject() + return tcAssemblyDataOpt + } + + /// Get the timestamp that would be on the output if fully built immediately + member private _.TryGetLogicalTimeStampForProject(cache, options) = + match tryGetBuilderNode options with + | Some lazyWork -> + match lazyWork.TryPeekValue() with + | ValueSome(Some builder, _) -> Some(builder.GetLogicalTimeStampForProject(cache)) + | _ -> None + | _ -> None + + /// Parse and typecheck the whole project. + member bc.ParseAndCheckProject(options, userOpName) = + use _ = + Activity.start + "BackgroundCompiler.ParseAndCheckProject" + [| + Activity.Tags.project, options.ProjectFileName + Activity.Tags.userOpName, userOpName + |] + + bc.ParseAndCheckProjectImpl(options, userOpName) + + member _.GetProjectOptionsFromScript + ( + fileName, + sourceText, + previewEnabled, + loadedTimeStamp, + otherFlags, + useFsiAuxLib: bool option, + useSdkRefs: bool option, + sdkDirOverride: string option, + assumeDotNetFramework: bool option, + optionsStamp: int64 option, + _userOpName + ) = + use _ = + Activity.start + "BackgroundCompiler.GetProjectOptionsFromScript" + [| Activity.Tags.fileName, fileName; Activity.Tags.userOpName, _userOpName |] + + cancellable { + // Do we add a reference to FSharp.Compiler.Interactive.Settings by default? + let useFsiAuxLib = defaultArg useFsiAuxLib true + let useSdkRefs = defaultArg useSdkRefs true + let reduceMemoryUsage = ReduceMemoryFlag.Yes + let previewEnabled = defaultArg previewEnabled false + + // Do we assume .NET Framework references for scripts? + let assumeDotNetFramework = defaultArg assumeDotNetFramework true + + let! ct = Cancellable.token () + use _ = Cancellable.UsingToken(ct) + + let extraFlags = + if previewEnabled then + [| "--langversion:preview" |] + else + [||] + + let otherFlags = defaultArg otherFlags extraFlags + + use diagnostics = new DiagnosticsScope(otherFlags |> Array.contains "--flaterrors") + + let useSimpleResolution = + otherFlags |> Array.exists (fun x -> x = "--simpleresolution") + + let loadedTimeStamp = defaultArg loadedTimeStamp DateTime.MaxValue // Not 'now', we don't want to force reloading + + let applyCompilerOptions tcConfigB = + let fsiCompilerOptions = GetCoreFsiCompilerOptions tcConfigB + ParseCompilerOptions(ignore, fsiCompilerOptions, Array.toList otherFlags) + + let loadClosure = + LoadClosure.ComputeClosureOfScriptText( + legacyReferenceResolver, + FSharpCheckerResultsSettings.defaultFSharpBinariesDir, + fileName, + sourceText, + CodeContext.Editing, + useSimpleResolution, + useFsiAuxLib, + useSdkRefs, + sdkDirOverride, + Lexhelp.LexResourceManager(), + applyCompilerOptions, + assumeDotNetFramework, + tryGetMetadataSnapshot, + reduceMemoryUsage, + dependencyProviderForScripts + ) + + let otherFlags = + [| + yield "--noframework" + yield "--warn:3" + yield! otherFlags + for r in loadClosure.References do + yield "-r:" + fst r + for code, _ in loadClosure.NoWarns do + yield "--nowarn:" + code + |] + + let options = + { + ProjectFileName = fileName + ".fsproj" // Make a name that is unique in this directory. + ProjectId = None + SourceFiles = loadClosure.SourceFiles |> List.map fst |> List.toArray + OtherOptions = otherFlags + ReferencedProjects = [||] + IsIncompleteTypeCheckEnvironment = false + UseScriptResolutionRules = true + LoadTime = loadedTimeStamp + UnresolvedReferences = Some(FSharpUnresolvedReferencesSet(loadClosure.UnresolvedReferences)) + OriginalLoadReferences = loadClosure.OriginalLoadReferences + Stamp = optionsStamp + } + + scriptClosureCache.Set(AnyCallerThread, options, loadClosure) // Save the full load closure for later correlation. + + let diags = + loadClosure.LoadClosureRootFileDiagnostics + |> List.map (fun (exn, isError) -> + FSharpDiagnostic.CreateFromException( + exn, + isError, + range.Zero, + false, + options.OtherOptions |> Array.contains "--flaterrors", + None + )) + + return options, (diags @ diagnostics.Diagnostics) + } + |> Cancellable.toAsync + + member bc.InvalidateConfiguration(options: FSharpProjectOptions, userOpName) = + use _ = + Activity.start + "BackgroundCompiler.InvalidateConfiguration" + [| + Activity.Tags.project, options.ProjectFileName + Activity.Tags.userOpName, userOpName + |] + + if incrementalBuildersCache.ContainsSimilarKey(AnyCallerThread, options) then + parseCacheLock.AcquireLock(fun ltok -> + for sourceFile in options.SourceFiles do + checkFileInProjectCache.RemoveAnySimilar(ltok, (sourceFile, 0L, options))) + + let _ = createBuilderNode (options, userOpName, CancellationToken.None) + () + + member bc.ClearCache(options: seq, _userOpName) = + use _ = + Activity.start "BackgroundCompiler.ClearCache" [| Activity.Tags.userOpName, _userOpName |] + + lock gate (fun () -> + options + |> Seq.iter (fun options -> + incrementalBuildersCache.RemoveAnySimilar(AnyCallerThread, options) + + parseCacheLock.AcquireLock(fun ltok -> + for sourceFile in options.SourceFiles do + checkFileInProjectCache.RemoveAnySimilar(ltok, (sourceFile, 0L, options))))) + + member _.NotifyProjectCleaned(options: FSharpProjectOptions, userOpName) = + use _ = + Activity.start + "BackgroundCompiler.NotifyProjectCleaned" + [| + Activity.Tags.project, options.ProjectFileName + Activity.Tags.userOpName, userOpName + |] + + async { + + let! ct = Async.CancellationToken + // If there was a similar entry (as there normally will have been) then re-establish an empty builder . This + // is a somewhat arbitrary choice - it will have the effect of releasing memory associated with the previous + // builder, but costs some time. + if incrementalBuildersCache.ContainsSimilarKey(AnyCallerThread, options) then + let _ = createBuilderNode (options, userOpName, ct) + () + } + + member _.BeforeBackgroundFileCheck = beforeFileChecked.Publish + + member _.FileParsed = fileParsed.Publish + + member _.FileChecked = fileChecked.Publish + + member _.ProjectChecked = projectChecked.Publish + + member _.ClearCaches() = + use _ = Activity.startNoTags "BackgroundCompiler.ClearCaches" + + lock gate (fun () -> + parseCacheLock.AcquireLock(fun ltok -> + checkFileInProjectCache.Clear(ltok) + parseFileCache.Clear(ltok)) + + incrementalBuildersCache.Clear(AnyCallerThread) + frameworkTcImportsCache.Clear() + scriptClosureCache.Clear AnyCallerThread) + + member _.DownsizeCaches() = + use _ = Activity.startNoTags "BackgroundCompiler.DownsizeCaches" + + lock gate (fun () -> + parseCacheLock.AcquireLock(fun ltok -> + checkFileInProjectCache.Resize(ltok, newKeepStrongly = 1) + parseFileCache.Resize(ltok, newKeepStrongly = 1)) + + incrementalBuildersCache.Resize(AnyCallerThread, newKeepStrongly = 1, newKeepMax = 1) + frameworkTcImportsCache.Downsize() + scriptClosureCache.Resize(AnyCallerThread, newKeepStrongly = 1, newKeepMax = 1)) + + member _.FrameworkImportsCache = frameworkTcImportsCache + + static member ActualParseFileCount = actualParseFileCount + + static member ActualCheckFileCount = actualCheckFileCount + + interface IBackgroundCompiler with + + member _.BeforeBackgroundFileCheck = self.BeforeBackgroundFileCheck + + member _.CheckFileInProject + ( + parseResults: FSharpParseFileResults, + fileName: string, + fileVersion: int, + sourceText: ISourceText, + options: FSharpProjectOptions, + userOpName: string + ) : NodeCode = + self.CheckFileInProject(parseResults, fileName, fileVersion, sourceText, options, userOpName) + + member _.CheckFileInProjectAllowingStaleCachedResults + ( + parseResults: FSharpParseFileResults, + fileName: string, + fileVersion: int, + sourceText: ISourceText, + options: FSharpProjectOptions, + userOpName: string + ) : NodeCode = + self.CheckFileInProjectAllowingStaleCachedResults(parseResults, fileName, fileVersion, sourceText, options, userOpName) + + member _.ClearCache(options: seq, userOpName: string) : unit = self.ClearCache(options, userOpName) + + member _.ClearCache(projects: ProjectSnapshot.FSharpProjectIdentifier seq, userOpName: string) = ignore (projects, userOpName) + + member _.ClearCaches() : unit = self.ClearCaches() + member _.DownsizeCaches() : unit = self.DownsizeCaches() + member _.FileChecked: IEvent = self.FileChecked + member _.FileParsed: IEvent = self.FileParsed + + member _.FindReferencesInFile + ( + fileName: string, + options: FSharpProjectOptions, + symbol: FSharpSymbol, + canInvalidateProject: bool, + userOpName: string + ) : NodeCode> = + self.FindReferencesInFile(fileName, options, symbol, canInvalidateProject, userOpName) + + member this.FindReferencesInFile(fileName, projectSnapshot, symbol, userOpName) = + this.FindReferencesInFile(fileName, projectSnapshot.ToOptions(), symbol, true, userOpName) + + member _.FrameworkImportsCache: FrameworkImportsCache = self.FrameworkImportsCache + + member _.GetAssemblyData + ( + options: FSharpProjectOptions, + _fileName: string, + userOpName: string + ) : NodeCode = + self.GetAssemblyData(options, userOpName) + + member _.GetAssemblyData + ( + projectSnapshot: FSharpProjectSnapshot, + _fileName: string, + userOpName: string + ) : NodeCode = + self.GetAssemblyData(projectSnapshot.ToOptions(), userOpName) + + member _.GetBackgroundCheckResultsForFileInProject + ( + fileName: string, + options: FSharpProjectOptions, + userOpName: string + ) : NodeCode = + self.GetBackgroundCheckResultsForFileInProject(fileName, options, userOpName) + + member _.GetBackgroundParseResultsForFileInProject + ( + fileName: string, + options: FSharpProjectOptions, + userOpName: string + ) : NodeCode = + self.GetBackgroundParseResultsForFileInProject(fileName, options, userOpName) + + member _.GetCachedCheckFileResult + ( + builder: IncrementalBuilder, + fileName: string, + sourceText: ISourceText, + options: FSharpProjectOptions + ) : NodeCode<(FSharpParseFileResults * FSharpCheckFileResults) option> = + self.GetCachedCheckFileResult(builder, fileName, sourceText, options) + + member _.GetProjectOptionsFromScript + ( + fileName: string, + sourceText: ISourceText, + previewEnabled: bool option, + loadedTimeStamp: DateTime option, + otherFlags: string array option, + useFsiAuxLib: bool option, + useSdkRefs: bool option, + sdkDirOverride: string option, + assumeDotNetFramework: bool option, + optionsStamp: int64 option, + userOpName: string + ) : Async = + self.GetProjectOptionsFromScript( + fileName, + sourceText, + previewEnabled, + loadedTimeStamp, + otherFlags, + useFsiAuxLib, + useSdkRefs, + sdkDirOverride, + assumeDotNetFramework, + optionsStamp, + userOpName + ) + + member _.GetSemanticClassificationForFile + ( + fileName: string, + options: FSharpProjectOptions, + userOpName: string + ) : NodeCode = + self.GetSemanticClassificationForFile(fileName, options, userOpName) + + member _.GetSemanticClassificationForFile + ( + fileName: string, + snapshot: FSharpProjectSnapshot, + userOpName: string + ) : NodeCode = + self.GetSemanticClassificationForFile(fileName, snapshot.ToOptions(), userOpName) + + member _.InvalidateConfiguration(options: FSharpProjectOptions, userOpName: string) : unit = + self.InvalidateConfiguration(options, userOpName) + + member _.NotifyFileChanged(fileName: string, options: FSharpProjectOptions, userOpName: string) : NodeCode = + self.NotifyFileChanged(fileName, options, userOpName) + + member _.NotifyProjectCleaned(options: FSharpProjectOptions, userOpName: string) : Async = + self.NotifyProjectCleaned(options, userOpName) + + member _.ParseAndCheckFileInProject + ( + fileName: string, + fileVersion: int, + sourceText: ISourceText, + options: FSharpProjectOptions, + userOpName: string + ) : NodeCode = + self.ParseAndCheckFileInProject(fileName, fileVersion, sourceText, options, userOpName) + + member _.ParseAndCheckFileInProject + ( + fileName: string, + projectSnapshot: FSharpProjectSnapshot, + userOpName: string + ) : NodeCode = + node { + let fileSnapshot = + projectSnapshot.ProjectSnapshot.SourceFiles + |> Seq.find (fun f -> f.FileName = fileName) + + let! sourceText = fileSnapshot.GetSource() |> NodeCode.AwaitTask + let options = projectSnapshot.ToOptions() + + return! self.ParseAndCheckFileInProject(fileName, 0, sourceText, options, userOpName) + } + + member _.ParseAndCheckProject(options: FSharpProjectOptions, userOpName: string) : NodeCode = + self.ParseAndCheckProject(options, userOpName) + + member _.ParseAndCheckProject(projectSnapshot: FSharpProjectSnapshot, userOpName: string) : NodeCode = + self.ParseAndCheckProject(projectSnapshot.ToOptions(), userOpName) + + member _.ParseFile + ( + fileName: string, + sourceText: ISourceText, + options: FSharpParsingOptions, + cache: bool, + flatErrors: bool, + userOpName: string + ) = + self.ParseFile(fileName, sourceText, options, cache, flatErrors, userOpName) + + member _.ParseFile(fileName: string, projectSnapshot: FSharpProjectSnapshot, userOpName: string) = + let options = projectSnapshot.ToOptions() + + self.GetBackgroundParseResultsForFileInProject(fileName, options, userOpName) + |> Async.AwaitNodeCode + + member _.ProjectChecked: IEvent = self.ProjectChecked + + member _.TryGetRecentCheckResultsForFile + ( + fileName: string, + options: FSharpProjectOptions, + sourceText: ISourceText option, + userOpName: string + ) : (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option = + self.TryGetRecentCheckResultsForFile(fileName, options, sourceText, userOpName) diff --git a/src/Compiler/Service/BackgroundCompiler.fsi b/src/Compiler/Service/BackgroundCompiler.fsi new file mode 100644 index 00000000000..f3bf3c96ccc --- /dev/null +++ b/src/Compiler/Service/BackgroundCompiler.fsi @@ -0,0 +1,224 @@ +namespace FSharp.Compiler.CodeAnalysis + +open FSharp.Compiler.Text +open FSharp.Compiler.BuildGraph + +open System.Reflection +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.CompilerConfig +open FSharp.Compiler.Diagnostics + +type SourceTextHash = int64 + +type CacheStamp = int64 + +type FileName = string + +type FilePath = string + +type ProjectPath = string + +type FileVersion = int + +type FSharpProjectSnapshot = ProjectSnapshot.FSharpProjectSnapshot + +type internal IBackgroundCompiler = + + /// Type-check the result obtained by parsing. Force the evaluation of the antecedent type checking context if needed. + abstract CheckFileInProject: + parseResults: FSharpParseFileResults * + fileName: string * + fileVersion: int * + sourceText: ISourceText * + options: FSharpProjectOptions * + userOpName: string -> + NodeCode + + /// Type-check the result obtained by parsing, but only if the antecedent type checking context is available. + abstract CheckFileInProjectAllowingStaleCachedResults: + parseResults: FSharpParseFileResults * + fileName: string * + fileVersion: int * + sourceText: ISourceText * + options: FSharpProjectOptions * + userOpName: string -> + NodeCode + + abstract ClearCache: options: FSharpProjectOptions seq * userOpName: string -> unit + + abstract ClearCache: projects: ProjectSnapshot.FSharpProjectIdentifier seq * userOpName: string -> unit + + abstract ClearCaches: unit -> unit + + abstract DownsizeCaches: unit -> unit + + abstract FindReferencesInFile: + fileName: string * + projectSnapshot: FSharpProjectSnapshot * + symbol: FSharp.Compiler.Symbols.FSharpSymbol * + userOpName: string -> + NodeCode + + abstract FindReferencesInFile: + fileName: string * + options: FSharpProjectOptions * + symbol: FSharp.Compiler.Symbols.FSharpSymbol * + canInvalidateProject: bool * + userOpName: string -> + NodeCode + + abstract GetAssemblyData: + projectSnapshot: FSharpProjectSnapshot * outputFileName: string * userOpName: string -> + NodeCode + + abstract GetAssemblyData: + options: FSharpProjectOptions * outputFileName: string * userOpName: string -> + NodeCode + + /// Fetch the check information from the background compiler (which checks w.r.t. the FileSystem API) + abstract GetBackgroundCheckResultsForFileInProject: + fileName: string * options: FSharpProjectOptions * userOpName: string -> + NodeCode + + /// Fetch the parse information from the background compiler (which checks w.r.t. the FileSystem API) + abstract GetBackgroundParseResultsForFileInProject: + fileName: string * options: FSharpProjectOptions * userOpName: string -> NodeCode + + abstract GetCachedCheckFileResult: + builder: IncrementalBuilder * fileName: string * sourceText: ISourceText * options: FSharpProjectOptions -> + NodeCode<(FSharpParseFileResults * FSharpCheckFileResults) option> + + abstract GetProjectOptionsFromScript: + fileName: string * + sourceText: ISourceText * + previewEnabled: bool option * + loadedTimeStamp: System.DateTime option * + otherFlags: string array option * + useFsiAuxLib: bool option * + useSdkRefs: bool option * + sdkDirOverride: string option * + assumeDotNetFramework: bool option * + optionsStamp: int64 option * + userOpName: string -> + Async + + abstract GetSemanticClassificationForFile: + fileName: string * snapshot: FSharpProjectSnapshot * userOpName: string -> + NodeCode + + abstract GetSemanticClassificationForFile: + fileName: string * options: FSharpProjectOptions * userOpName: string -> + NodeCode + + abstract InvalidateConfiguration: options: FSharpProjectOptions * userOpName: string -> unit + + abstract NotifyFileChanged: fileName: string * options: FSharpProjectOptions * userOpName: string -> NodeCode + + abstract NotifyProjectCleaned: options: FSharpProjectOptions * userOpName: string -> Async + + abstract ParseAndCheckFileInProject: + fileName: string * projectSnapshot: FSharpProjectSnapshot * userOpName: string -> + NodeCode + + /// Parses and checks the source file and returns untyped AST and check results. + abstract ParseAndCheckFileInProject: + fileName: string * + fileVersion: int * + sourceText: ISourceText * + options: FSharpProjectOptions * + userOpName: string -> + NodeCode + + abstract ParseAndCheckProject: + projectSnapshot: FSharpProjectSnapshot * userOpName: string -> NodeCode + + /// Parse and typecheck the whole project. + abstract ParseAndCheckProject: + options: FSharpProjectOptions * userOpName: string -> NodeCode + + abstract ParseFile: + fileName: string * projectSnapshot: FSharpProjectSnapshot * userOpName: string -> Async + + abstract ParseFile: + fileName: string * + sourceText: ISourceText * + options: FSharpParsingOptions * + cache: bool * + flatErrors: bool * + userOpName: string -> + Async + + /// Try to get recent approximate type check results for a file. + abstract TryGetRecentCheckResultsForFile: + fileName: string * options: FSharpProjectOptions * sourceText: ISourceText option * userOpName: string -> + (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option + + abstract BeforeBackgroundFileCheck: IEvent + + abstract FileChecked: IEvent + + abstract FileParsed: IEvent + + abstract FrameworkImportsCache: FrameworkImportsCache + + abstract ProjectChecked: IEvent + +[] +module internal EnvMisc = + + val braceMatchCacheSize: int + + val parseFileCacheSize: int + + val checkFileInProjectCacheSize: int + + val projectCacheSizeDefault: int + + val frameworkTcImportsCacheStrongSize: int + +[] +module internal Helpers = + + /// Determine whether two (fileName,options) keys are identical w.r.t. affect on checking + val AreSameForChecking2: (string * FSharpProjectOptions) * (string * FSharpProjectOptions) -> bool + + /// Determine whether two (fileName,options) keys should be identical w.r.t. resource usage + val AreSubsumable2: (string * FSharpProjectOptions) * (string * FSharpProjectOptions) -> bool + + /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. parsing + val AreSameForParsing: (string * int64 * 'a) * (string * int64 * 'a) -> bool when 'a: equality + + val AreSimilarForParsing: ('a * 'b * 'c) * ('a * 'd * 'e) -> bool when 'a: equality + + /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. checking + val AreSameForChecking3: (string * int64 * FSharpProjectOptions) * (string * int64 * FSharpProjectOptions) -> bool + + /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. resource usage + val AreSubsumable3: (string * 'a * FSharpProjectOptions) * (string * 'b * FSharpProjectOptions) -> bool + + /// If a symbol is an attribute check if given set of names contains its name without the Attribute suffix + val NamesContainAttribute: symbol: FSharp.Compiler.Symbols.FSharpSymbol -> names: Set -> bool + +type internal BackgroundCompiler = + interface IBackgroundCompiler + + new: + legacyReferenceResolver: LegacyReferenceResolver * + projectCacheSize: int * + keepAssemblyContents: bool * + keepAllBackgroundResolutions: bool * + tryGetMetadataSnapshot: FSharp.Compiler.AbstractIL.ILBinaryReader.ILReaderTryGetMetadataSnapshot * + suggestNamesForErrors: bool * + keepAllBackgroundSymbolUses: bool * + enableBackgroundItemKeyStoreAndSemanticClassification: bool * + enablePartialTypeChecking: bool * + parallelReferenceResolution: ParallelReferenceResolution * + captureIdentifiersWhenParsing: bool * + getSource: (string -> Async) option * + useChangeNotifications: bool * + useSyntaxTreeCache: bool -> + BackgroundCompiler + + static member ActualCheckFileCount: int + + static member ActualParseFileCount: int diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs index 2b23d85a7ce..5f18a90968a 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fs +++ b/src/Compiler/Service/FSharpCheckerResults.fs @@ -6,6 +6,7 @@ namespace FSharp.Compiler.CodeAnalysis open System +open System.Collections.Generic open System.Diagnostics open System.IO open System.Reflection @@ -53,6 +54,9 @@ open FSharp.Compiler.TypedTreeOps open Internal.Utilities open Internal.Utilities.Collections open FSharp.Compiler.AbstractIL.ILBinaryReader +open System.Threading.Tasks +open System.Runtime.CompilerServices +open Internal.Utilities.Hashing type FSharpUnresolvedReferencesSet = FSharpUnresolvedReferencesSet of UnresolvedAssemblyReference list @@ -483,6 +487,8 @@ type internal TypeCheckInfo // // If we're looking for members using a residue, we'd expect only // a single item (pick the first one) and we need the residue (which may be "") + | CNR(_, ItemOccurence.InvalidUse, _, _, _, _) :: _, _ -> NameResResult.Empty + | CNR(Item.Types(_, ty :: _), _, denv, nenv, ad, m) :: _, Some _ -> let targets = ResolveCompletionTargets.All(ConstraintSolver.IsApplicableMethApprox g amap m) @@ -891,7 +897,6 @@ type internal TypeCheckInfo let CompletionItem (ty: TyconRef voption) (assemblySymbol: AssemblySymbol voption) (item: ItemWithInst) = let kind = match item.Item with - | Item.FakeInterfaceCtor _ | Item.DelegateCtor _ | Item.CtorGroup _ -> CompletionItemKind.Method false | Item.MethodGroup(_, minfos, _) -> @@ -1802,7 +1807,6 @@ type internal TypeCheckInfo match d.Item with | Item.Types(_, AbbrevOrAppTy tcref :: _) -> 1 + tcref.TyparsNoRange.Length // Put delegate ctors after types, sorted by #typars. RemoveDuplicateItems will remove FakeInterfaceCtor and DelegateCtor if an earlier type is also reported with this name - | Item.FakeInterfaceCtor(AbbrevOrAppTy tcref) | Item.DelegateCtor(AbbrevOrAppTy tcref) -> 1000 + tcref.TyparsNoRange.Length // Put type ctors after types, sorted by #typars. RemoveDuplicateItems will remove DefaultStructCtors if a type is also reported with this name | Item.CtorGroup(_, cinfo :: _) -> 1000 + 10 * cinfo.DeclaringTyconRef.TyparsNoRange.Length @@ -1822,7 +1826,6 @@ type internal TypeCheckInfo | Item.Types(_, AbbrevOrAppTy tcref :: _) | Item.ExnCase tcref -> tcref.LogicalName | Item.UnqualifiedType(tcref :: _) - | Item.FakeInterfaceCtor(AbbrevOrAppTy tcref) | Item.DelegateCtor(AbbrevOrAppTy tcref) -> tcref.CompiledName | Item.CtorGroup(_, cinfo :: _) -> cinfo.ApparentEnclosingTyconRef.CompiledName | _ -> d.Item.DisplayName) @@ -1909,7 +1912,7 @@ type internal TypeCheckInfo | Some(_, lines) -> let lines = lines - |> List.filter (fun line -> not (line.StartsWith("//")) && not (String.IsNullOrEmpty line)) + |> List.filter (fun line -> not (line.StartsWithOrdinal("//")) && not (String.IsNullOrEmpty line)) ToolTipText.ToolTipText [ @@ -2252,7 +2255,7 @@ type internal TypeCheckInfo | Some itemRange -> let projectDir = FileSystem.GetDirectoryNameShim( - if projectFileName = "" then + if String.IsNullOrEmpty(projectFileName) then mainInputFileName else projectFileName @@ -2516,6 +2519,11 @@ module internal ParseAndCheckFile = member _.AnyErrors = errorCount > 0 + member _.CollectedPhasedDiagnostics = + [| + for struct (diagnostic, severity) in diagnosticsCollector -> diagnostic, severity + |] + member _.CollectedDiagnostics(symbolEnv: SymbolEnv option) = [| for struct (diagnostic, severity) in diagnosticsCollector do @@ -3271,7 +3279,7 @@ type FSharpCheckFileResults tcConfig, tcGlobals, isIncompleteTypeCheckEnvironment: bool, - builder: IncrementalBuilder, + builder: IncrementalBuilder option, projectOptions, dependencyFiles, creationErrors: FSharpDiagnostic[], @@ -3312,7 +3320,7 @@ type FSharpCheckFileResults let errors = FSharpCheckFileResults.JoinErrors(isIncompleteTypeCheckEnvironment, creationErrors, parseErrors, tcErrors) - FSharpCheckFileResults(mainInputFileName, errors, Some tcFileInfo, dependencyFiles, Some builder, keepAssemblyContents) + FSharpCheckFileResults(mainInputFileName, errors, Some tcFileInfo, dependencyFiles, builder, keepAssemblyContents) static member CheckOneFile ( @@ -3329,7 +3337,7 @@ type FSharpCheckFileResults backgroundDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity)[], isIncompleteTypeCheckEnvironment: bool, projectOptions: FSharpProjectOptions, - builder: IncrementalBuilder, + builder: IncrementalBuilder option, dependencyFiles: string[], creationErrors: FSharpDiagnostic[], parseErrors: FSharpDiagnostic[], @@ -3358,7 +3366,7 @@ type FSharpCheckFileResults FSharpCheckFileResults.JoinErrors(isIncompleteTypeCheckEnvironment, creationErrors, parseErrors, tcErrors) let results = - FSharpCheckFileResults(mainInputFileName, errors, Some tcFileInfo, dependencyFiles, Some builder, keepAssemblyContents) + FSharpCheckFileResults(mainInputFileName, errors, Some tcFileInfo, dependencyFiles, builder, keepAssemblyContents) return results } @@ -3376,7 +3384,7 @@ type FSharpCheckProjectResults TcImports * CcuThunk * ModuleOrNamespaceType * - Choice * + Choice> * TopAttribs option * (unit -> IRawFSharpAssemblyData option) * ILAssemblyRef * @@ -3414,6 +3422,7 @@ type FSharpCheckProjectResults FSharpAssemblySignature(tcGlobals, thisCcu, ccuSig, tcImports, topAttribs, ccuSig) + // TODO: Looks like we don't need this member _.TypedImplementationFiles = if not keepAssemblyContents then invalidOp @@ -3474,6 +3483,7 @@ type FSharpCheckProjectResults FSharpAssemblyContents(tcGlobals, thisCcu, Some ccuSig, tcImports, mimpls) // Not, this does not have to be a SyncOp, it can be called from any thread + // TODO: this should be async member _.GetUsesOfSymbol(symbol: FSharpSymbol, ?cancellationToken: CancellationToken) = let _, _, _, _, builderOrSymbolUses, _, _, _, _, _, _, _ = getDetails () @@ -3489,7 +3499,20 @@ type FSharpCheckProjectResults | Some(_, tcInfoExtras) -> tcInfoExtras.TcSymbolUses.GetUsesOfSymbol symbol.Item | _ -> [||] | _ -> [||]) - | Choice2Of2 tcSymbolUses -> tcSymbolUses.GetUsesOfSymbol symbol.Item + |> Array.toSeq + | Choice2Of2 task -> + Async.RunSynchronously( + async { + let! tcSymbolUses = task + + return + seq { + for symbolUses in tcSymbolUses do + yield! symbolUses.GetUsesOfSymbol symbol.Item + } + }, + ?cancellationToken = cancellationToken + ) results |> Seq.filter (fun symbolUse -> symbolUse.ItemOccurence <> ItemOccurence.RelatedText) @@ -3501,6 +3524,7 @@ type FSharpCheckProjectResults |> Seq.toArray // Not, this does not have to be a SyncOp, it can be called from any thread + // TODO: this should be async member _.GetAllUsesOfAllSymbols(?cancellationToken: CancellationToken) = let tcGlobals, tcImports, thisCcu, ccuSig, builderOrSymbolUses, _, _, _, _, _, _, _ = getDetails () @@ -3519,7 +3543,8 @@ type FSharpCheckProjectResults | Some(_, tcInfoExtras) -> tcInfoExtras.TcSymbolUses | _ -> TcSymbolUses.Empty | _ -> TcSymbolUses.Empty) - | Choice2Of2 tcSymbolUses -> [| tcSymbolUses |] + |> Array.toSeq + | Choice2Of2 tcSymbolUses -> Async.RunSynchronously(tcSymbolUses, ?cancellationToken = cancellationToken) [| for r in tcSymbolUses do @@ -3560,9 +3585,6 @@ type FsiInteractiveChecker(legacyReferenceResolver, tcConfig: TcConfig, tcGlobal member _.ParseAndCheckInteraction(sourceText: ISourceText, ?userOpName: string) = cancellable { - let! ct = Cancellable.token () - use _ = Cancellable.UsingToken(ct) - let userOpName = defaultArg userOpName "Unknown" let fileName = Path.Combine(tcConfig.implicitIncludeDir, "stdin.fsx") let suggestNamesForErrors = true // Will always be true, this is just for readability @@ -3658,7 +3680,7 @@ type FsiInteractiveChecker(legacyReferenceResolver, tcConfig: TcConfig, tcGlobal tcImports, tcFileInfo.ThisCcu, tcFileInfo.CcuSigForFile, - Choice2Of2 tcFileInfo.ScopeSymbolUses, + Choice2Of2(tcFileInfo.ScopeSymbolUses |> Seq.singleton |> async.Return), None, (fun () -> None), mkSimpleAssemblyRef "stdin", diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi index 8cdb304c18a..26781c4356e 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fsi +++ b/src/Compiler/Service/FSharpCheckerResults.fsi @@ -3,8 +3,10 @@ namespace FSharp.Compiler.CodeAnalysis open System +open System.Collections.Generic open System.IO open System.Threading +open System.Threading.Tasks open Internal.Utilities.Library open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.ILBinaryReader @@ -26,6 +28,8 @@ open FSharp.Compiler.TypedTreeOps open FSharp.Compiler.TcGlobals open FSharp.Compiler.Text +open Internal.Utilities.Collections + /// Delays the creation of an ILModuleReader [] type DelayedILModuleReader = @@ -443,7 +447,7 @@ type public FSharpCheckFileResults = tcConfig: TcConfig * tcGlobals: TcGlobals * isIncompleteTypeCheckEnvironment: bool * - builder: IncrementalBuilder * + builder: IncrementalBuilder option * projectOptions: FSharpProjectOptions * dependencyFiles: string[] * creationErrors: FSharpDiagnostic[] * @@ -477,7 +481,7 @@ type public FSharpCheckFileResults = backgroundDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity)[] * isIncompleteTypeCheckEnvironment: bool * projectOptions: FSharpProjectOptions * - builder: IncrementalBuilder * + builder: IncrementalBuilder option * dependencyFiles: string[] * creationErrors: FSharpDiagnostic[] * parseErrors: FSharpDiagnostic[] * @@ -537,7 +541,7 @@ type public FSharpCheckProjectResults = TcImports * CcuThunk * ModuleOrNamespaceType * - Choice * + Choice> * TopAttribs option * (unit -> IRawFSharpAssemblyData option) * ILAssemblyRef * @@ -569,6 +573,29 @@ module internal ParseAndCheckFile = ct: CancellationToken -> (range * range)[] + /// Diagnostics handler for parsing & type checking while processing a single file + type DiagnosticsHandler = + new: + reportErrors: bool * + mainInputFileName: string * + diagnosticsOptions: FSharpDiagnosticOptions * + sourceText: ISourceText * + suggestNamesForErrors: bool * + flatErrors: bool -> + DiagnosticsHandler + + member DiagnosticsLogger: DiagnosticsLogger + + member ErrorCount: int + + member DiagnosticOptions: FSharpDiagnosticOptions with set + + member AnyErrors: bool + + member CollectedPhasedDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) array + + member CollectedDiagnostics: symbolEnv: SymbolEnv option -> FSharpDiagnostic array + // An object to typecheck source in a given typechecking environment. // Used internally to provide intellisense over F# Interactive. type internal FsiInteractiveChecker = diff --git a/src/Compiler/Service/FSharpParseFileResults.fs b/src/Compiler/Service/FSharpParseFileResults.fs index 46a5753ba3f..baea32da816 100644 --- a/src/Compiler/Service/FSharpParseFileResults.fs +++ b/src/Compiler/Service/FSharpParseFileResults.fs @@ -6,7 +6,6 @@ open System open System.IO open System.Collections.Generic open System.Diagnostics -open Internal.Utilities.Library open FSharp.Compiler.Diagnostics open FSharp.Compiler.EditorServices open FSharp.Compiler.Syntax @@ -115,201 +114,118 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, | _ -> Some workingRange - let visitor = - { new SyntaxVisitorBase<_>() with - override _.VisitExpr(_, _, defaultTraverse, expr) = defaultTraverse expr - - override _.VisitBinding(_path, defaultTraverse, binding) = - match binding with - | SynBinding(valData = SynValData(memberFlags = None); expr = expr) as b when - rangeContainsPos b.RangeOfBindingWithRhs pos - -> - match tryGetIdentRangeFromBinding b with - | Some range -> walkBinding expr range - | None -> None - | _ -> defaultTraverse binding - } - - SyntaxTraversal.Traverse(pos, input, visitor) + (pos, input) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynBinding(SynBinding(valData = SynValData(memberFlags = None); expr = expr) as b) when + rangeContainsPos b.RangeOfBindingWithRhs pos + -> + match tryGetIdentRangeFromBinding b with + | Some range -> walkBinding expr range + | None -> None + | _ -> None) member _.TryIdentOfPipelineContainingPosAndNumArgsApplied pos = - let visitor = - { new SyntaxVisitorBase<_>() with - member _.VisitExpr(_, _, defaultTraverse, expr) = - match expr with - | SynExpr.App(_, _, SynExpr.App(_, true, SynExpr.LongIdent(longDotId = SynLongIdent(id = [ ident ])), _, _), argExpr, _) when - rangeContainsPos argExpr.Range pos - -> - match argExpr with - | SynExpr.App(_, _, _, SynExpr.Paren(expr, _, _, _), _) when rangeContainsPos expr.Range pos -> None - | _ -> - if ident.idText = "op_PipeRight" then Some(ident, 1) - elif ident.idText = "op_PipeRight2" then Some(ident, 2) - elif ident.idText = "op_PipeRight3" then Some(ident, 3) - else None - | _ -> defaultTraverse expr - } - - SyntaxTraversal.Traverse(pos, input, visitor) + (pos, input) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynExpr(SynExpr.App( + funcExpr = SynExpr.App(_, true, SynExpr.LongIdent(longDotId = SynLongIdent(id = [ ident ])), _, _); argExpr = argExpr)) when + rangeContainsPos argExpr.Range pos + -> + match argExpr with + | SynExpr.App(_, _, _, SynExpr.Paren(expr, _, _, _), _) when rangeContainsPos expr.Range pos -> None + | _ -> + if ident.idText = "op_PipeRight" then Some(ident, 1) + elif ident.idText = "op_PipeRight2" then Some(ident, 2) + elif ident.idText = "op_PipeRight3" then Some(ident, 3) + else None + | _ -> None) member _.IsPosContainedInApplication pos = - let visitor = - { new SyntaxVisitorBase<_>() with - member _.VisitExpr(_, traverseSynExpr, defaultTraverse, expr) = - match expr with - | SynExpr.TypeApp(_, _, _, _, _, _, range) when rangeContainsPos range pos -> Some range - | SynExpr.App(_, _, _, SynExpr.ComputationExpr(_, expr, _), range) when rangeContainsPos range pos -> - traverseSynExpr expr - | SynExpr.App(_, _, _, _, range) when rangeContainsPos range pos -> Some range - | _ -> defaultTraverse expr - } - - let result = SyntaxTraversal.Traverse(pos, input, visitor) - result.IsSome + (pos, input) + ||> ParsedInput.exists (fun _path node -> + match node with + | SyntaxNode.SynExpr(SynExpr.App(argExpr = SynExpr.ComputationExpr _) | SynExpr.TypeApp(expr = SynExpr.ComputationExpr _)) -> + false + | SyntaxNode.SynExpr(SynExpr.App(range = range) | SynExpr.TypeApp(range = range)) when rangeContainsPos range pos -> true + | _ -> false) member _.IsTypeName(range: range) = - let visitor = - { new SyntaxVisitorBase<_>() with - member _.VisitModuleDecl(_, _, synModuleDecl) = - match synModuleDecl with - | SynModuleDecl.Types(typeDefns, _) -> - typeDefns - |> Seq.exists (fun (SynTypeDefn(typeInfo, _, _, _, _, _)) -> typeInfo.Range = range) - |> Some - | _ -> None - } - - let result = SyntaxTraversal.Traverse(range.Start, input, visitor) - result |> Option.contains true + (range.Start, input) + ||> ParsedInput.exists (fun _path node -> + match node with + | SyntaxNode.SynTypeDefn(SynTypeDefn(typeInfo = typeInfo)) -> typeInfo.Range = range + | _ -> false) member _.TryRangeOfFunctionOrMethodBeingApplied pos = - let rec getIdentRangeForFuncExprInApp traverseSynExpr expr pos = - match expr with - | SynExpr.Ident ident -> Some ident.idRange - - | SynExpr.LongIdent(_, _, _, range) -> Some range - - | SynExpr.Paren(expr, _, _, range) when rangeContainsPos range pos -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos - - | SynExpr.TypeApp(expr, _, _, _, _, _, _) -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos - - | SynExpr.App(_, _, funcExpr, argExpr, _) -> - match argExpr with - | SynExpr.App(_, _, _, _, range) when rangeContainsPos range pos -> - getIdentRangeForFuncExprInApp traverseSynExpr argExpr pos - - // Special case: `async { ... }` is actually a ComputationExpr inside of the argExpr of a SynExpr.App - | SynExpr.ComputationExpr(_, expr, range) - | SynExpr.Paren(expr, _, _, range) when rangeContainsPos range pos -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos - - // Yielding values in an array or list that is used as an argument: List.sum [ getVal a b; getVal b c ] - | SynExpr.ArrayOrListComputed(_, expr, range) when rangeContainsPos range pos -> - if rangeContainsPos expr.Range pos then - getIdentRangeForFuncExprInApp traverseSynExpr expr pos - else - (* - In cases like - - let test () = div [] [ - str "" - ; | - ] - - `ProvideParametersAsyncAux` currently works with the wrong symbol or - doesn't detect the previously applied arguments. - Until that is fixed, don't show any tooltips rather than the wrong signature. - *) - None - - | _ -> - match funcExpr with - | SynExpr.App(_, true, _, _, _) when rangeContainsPos argExpr.Range pos -> - // x |> List.map - // Don't dive into the funcExpr (the operator expr) - // because we dont want to offer sig help for that! - getIdentRangeForFuncExprInApp traverseSynExpr argExpr pos - | _ -> - // Generally, we want to dive into the func expr to get the range - // of the identifier of the function we're after - getIdentRangeForFuncExprInApp traverseSynExpr funcExpr pos - - | SynExpr.Sequential(_, _, expr1, expr2, range) when rangeContainsPos range pos -> - if rangeContainsPos expr1.Range pos then - getIdentRangeForFuncExprInApp traverseSynExpr expr1 pos - else - getIdentRangeForFuncExprInApp traverseSynExpr expr2 pos - - | SynExpr.LetOrUse(bindings = bindings; body = body; range = range) when rangeContainsPos range pos -> - let binding = - bindings |> List.tryFind (fun x -> rangeContainsPos x.RangeOfBindingWithRhs pos) - - match binding with - | Some(SynBinding.SynBinding(expr = expr)) -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos - | None -> getIdentRangeForFuncExprInApp traverseSynExpr body pos - - | SynExpr.IfThenElse(ifExpr = ifExpr; thenExpr = thenExpr; elseExpr = elseExpr; range = range) when rangeContainsPos range pos -> - if rangeContainsPos ifExpr.Range pos then - getIdentRangeForFuncExprInApp traverseSynExpr ifExpr pos - elif rangeContainsPos thenExpr.Range pos then - getIdentRangeForFuncExprInApp traverseSynExpr thenExpr pos - else - match elseExpr with - | None -> None - | Some expr -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos + let rec (|FuncIdent|_|) (node, path) = + match node, path with + | SyntaxNode.SynExpr(DeepestIdentifiedFuncInAppChain range), _ -> Some range + | SyntaxNode.SynExpr PossibleBareArg, DeepestIdentifiedFuncInPath range -> Some range + | SyntaxNode.SynExpr(Identifier range), _ -> Some range + | _ -> None - | SynExpr.Match(expr = expr; clauses = clauses; range = range) when rangeContainsPos range pos -> + and (|DeepestIdentifiedFuncInAppChain|_|) expr = + let (|Contains|_|) pos (expr: SynExpr) = if rangeContainsPos expr.Range pos then - getIdentRangeForFuncExprInApp traverseSynExpr expr pos + Some Contains else - let clause = - clauses |> List.tryFind (fun clause -> rangeContainsPos clause.Range pos) - - match clause with - | None -> None - | Some clause -> - match clause with - | SynMatchClause.SynMatchClause(whenExpr = whenExprOpt; resultExpr = resultExpr) -> - match whenExprOpt with - | None -> getIdentRangeForFuncExprInApp traverseSynExpr resultExpr pos - | Some whenExpr -> - if rangeContainsPos whenExpr.Range pos then - getIdentRangeForFuncExprInApp traverseSynExpr whenExpr pos - else - getIdentRangeForFuncExprInApp traverseSynExpr resultExpr pos - - // Ex: C.M(x, y, ...) <--- We want to find where in the tupled application the call is being made - | SynExpr.Tuple(_, exprs, _, tupRange) when rangeContainsPos tupRange pos -> - let expr = exprs |> List.tryFind (fun expr -> rangeContainsPos expr.Range pos) - - match expr with - | None -> None - | Some expr -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos - - // Capture the body of a lambda, often nested in a call to a collection function - | SynExpr.Lambda(body = body) when rangeContainsPos body.Range pos -> getIdentRangeForFuncExprInApp traverseSynExpr body pos + None - | SynExpr.DotLambda(expr = body) when rangeContainsPos body.Range pos -> getIdentRangeForFuncExprInApp traverseSynExpr body pos - - | SynExpr.Do(expr, range) when rangeContainsPos range pos -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos + match expr with + | SynExpr.App(argExpr = Contains pos & DeepestIdentifiedFuncInAppChain range) -> Some range + | SynExpr.App(isInfix = false; funcExpr = Identifier range | DeepestIdentifiedFuncInAppChain range) -> Some range + | SynExpr.TypeApp(expr = Identifier range) -> Some range + | SynExpr.Paren(expr = Contains pos & DeepestIdentifiedFuncInAppChain range) -> Some range + | _ -> None - | SynExpr.Assert(expr, range) when rangeContainsPos range pos -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos + and (|DeepestIdentifiedFuncInPath|_|) path = + match path with + | SyntaxNode.SynExpr(DeepestIdentifiedFuncInAppChain range) :: _ + | SyntaxNode.SynExpr PossibleBareArg :: DeepestIdentifiedFuncInPath range -> Some range + | _ -> None - | SynExpr.ArbitraryAfterError(_debugStr, range) when rangeContainsPos range pos -> Some range + and (|Identifier|_|) expr = + let (|Ident|) (ident: Ident) = ident.idRange - | expr -> traverseSynExpr expr + match expr with + | SynExpr.Ident(ident = Ident range) + | SynExpr.LongIdent(range = range) + | SynExpr.ArbitraryAfterError(range = range) -> Some range + | _ -> None - let visitor = - { new SyntaxVisitorBase<_>() with - member _.VisitExpr(_, traverseSynExpr, defaultTraverse, expr) = - match expr with - | SynExpr.TypeApp(expr, _, _, _, _, _, range) when rangeContainsPos range pos -> - getIdentRangeForFuncExprInApp traverseSynExpr expr pos - | SynExpr.App(_, _, _funcExpr, _, range) as app when rangeContainsPos range pos -> - getIdentRangeForFuncExprInApp traverseSynExpr app pos - | _ -> defaultTraverse expr - } + and (|PossibleBareArg|_|) expr = + match expr with + | SynExpr.App _ + | SynExpr.TypeApp _ + | SynExpr.Ident _ + | SynExpr.LongIdent _ + | SynExpr.Const _ + | SynExpr.Null _ + | SynExpr.InterpolatedString _ -> Some PossibleBareArg + + // f (g ‸) + | SynExpr.Paren(expr = SynExpr.Ident _ | SynExpr.LongIdent _; range = parenRange) when + rangeContainsPos parenRange pos + && not (expr.Range.End.IsAdjacentTo parenRange.End) + -> + None + + | SynExpr.Paren _ -> Some PossibleBareArg + | _ -> None - SyntaxTraversal.Traverse(pos, input, visitor) + match input |> ParsedInput.tryNode pos with + | Some(FuncIdent range) -> Some range + | Some _ -> None + | None -> + // The cursor is outside any existing node's range, + // so try to drill down into the nearest one. + (pos, input) + ||> ParsedInput.tryPickLast (fun path node -> + match node, path with + | FuncIdent range -> Some range + | _ -> None) member _.GetAllArgumentsForFunctionApplicationAtPosition pos = SynExprAppLocationsImpl.getAllCurriedArgsAtPosition pos input @@ -326,242 +242,161 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, false, SynExpr.App(ExprAtomicFlag.NonAtomic, true, Ident "op_EqualsGreater", actualParamListExpr, _), actualLambdaBodyExpr, - _) -> Some(actualParamListExpr, actualLambdaBodyExpr) + range) -> Some(range, actualParamListExpr, actualLambdaBodyExpr) | _ -> None - SyntaxTraversal.Traverse( - opGreaterEqualPos, - input, - { new SyntaxVisitorBase<_>() with - member _.VisitExpr(_, _, defaultTraverse, expr) = - match expr with - | SynExpr.Paren(InfixAppOfOpEqualsGreater(lambdaArgs, lambdaBody) as app, _, _, _) -> - Some(app.Range, lambdaArgs.Range, lambdaBody.Range) - | _ -> defaultTraverse expr - - member _.VisitBinding(_path, defaultTraverse, binding) = - match binding with - | SynBinding(kind = SynBindingKind.Normal; expr = InfixAppOfOpEqualsGreater(lambdaArgs, lambdaBody) as app) -> - Some(app.Range, lambdaArgs.Range, lambdaBody.Range) - | _ -> defaultTraverse binding - } - ) + (opGreaterEqualPos, input) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynExpr(SynExpr.Paren(expr = InfixAppOfOpEqualsGreater(range, lambdaArgs, lambdaBody))) + | SyntaxNode.SynBinding(SynBinding( + kind = SynBindingKind.Normal; expr = InfixAppOfOpEqualsGreater(range, lambdaArgs, lambdaBody))) -> + Some(range, lambdaArgs.Range, lambdaBody.Range) + | _ -> None) member _.TryRangeOfStringInterpolationContainingPos pos = - let visitor = - { new SyntaxVisitorBase<_>() with - member _.VisitExpr(_, _, defaultTraverse, expr) = - match expr with - | SynExpr.InterpolatedString(range = range) when rangeContainsPos range pos -> Some range - | _ -> defaultTraverse expr - } - - SyntaxTraversal.Traverse(pos, input, visitor) + (pos, input) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynExpr(SynExpr.InterpolatedString(range = range)) when rangeContainsPos range pos -> Some range + | _ -> None) member _.TryRangeOfExprInYieldOrReturn pos = - let visitor = - { new SyntaxVisitorBase<_>() with - member _.VisitExpr(_path, _, defaultTraverse, expr) = - match expr with - | SynExpr.YieldOrReturn(_, expr, range) - | SynExpr.YieldOrReturnFrom(_, expr, range) when rangeContainsPos range pos -> Some expr.Range - | _ -> defaultTraverse expr - } - - SyntaxTraversal.Traverse(pos, input, visitor) + (pos, input) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynExpr(SynExpr.YieldOrReturn(expr = expr; range = range) | SynExpr.YieldOrReturnFrom(expr = expr; range = range)) when + rangeContainsPos range pos + -> + Some expr.Range + | _ -> None) member _.TryRangeOfRecordExpressionContainingPos pos = - let visitor = - { new SyntaxVisitorBase<_>() with - member _.VisitExpr(_, _, defaultTraverse, expr) = - match expr with - | SynExpr.Record(_, _, _, range) when rangeContainsPos range pos -> Some range - | _ -> defaultTraverse expr - } - - SyntaxTraversal.Traverse(pos, input, visitor) + (pos, input) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynExpr(SynExpr.Record(range = range)) when rangeContainsPos range pos -> Some range + | _ -> None) member _.TryRangeOfRefCellDereferenceContainingPos expressionPos = - let visitor = - { new SyntaxVisitorBase<_>() with - member _.VisitExpr(_, _, defaultTraverse, expr) = - match expr with - | SynExpr.App(_, false, SynExpr.LongIdent(longDotId = SynLongIdent(id = [ funcIdent ])), expr, _) -> - if funcIdent.idText = "op_Dereference" && rangeContainsPos expr.Range expressionPos then - Some funcIdent.idRange - else - None - | _ -> defaultTraverse expr - } - - SyntaxTraversal.Traverse(expressionPos, input, visitor) + (expressionPos, input) + ||> ParsedInput.tryPick (fun _path node -> + let (|Ident|) (ident: Ident) = ident.idText + + match node with + | SyntaxNode.SynExpr(SynExpr.App( + isInfix = false + funcExpr = SynExpr.LongIdent(longDotId = SynLongIdent(id = [ funcIdent & Ident "op_Dereference" ])) + argExpr = argExpr)) when rangeContainsPos argExpr.Range expressionPos -> Some funcIdent.idRange + | _ -> None) member _.TryRangeOfExpressionBeingDereferencedContainingPos expressionPos = - let visitor = - { new SyntaxVisitorBase<_>() with - member _.VisitExpr(_, _, defaultTraverse, expr) = - match expr with - | SynExpr.App(_, false, SynExpr.LongIdent(longDotId = SynLongIdent(id = [ funcIdent ])), expr, _) -> - if funcIdent.idText = "op_Dereference" && rangeContainsPos expr.Range expressionPos then - Some expr.Range - else - None - | _ -> defaultTraverse expr - } - - SyntaxTraversal.Traverse(expressionPos, input, visitor) + (expressionPos, input) + ||> ParsedInput.tryPick (fun _path node -> + let (|Ident|) (ident: Ident) = ident.idText + + match node with + | SyntaxNode.SynExpr(SynExpr.App( + isInfix = false; funcExpr = SynExpr.LongIdent(longDotId = SynLongIdent(id = [ Ident "op_Dereference" ])); argExpr = argExpr)) when + rangeContainsPos argExpr.Range expressionPos + -> + Some argExpr.Range + | _ -> None) member _.TryRangeOfReturnTypeHint(symbolUseStart: pos, ?skipLambdas) = let skipLambdas = defaultArg skipLambdas true - SyntaxTraversal.Traverse( - symbolUseStart, - input, - { new SyntaxVisitorBase<_>() with - member _.VisitExpr(_path, _traverseSynExpr, defaultTraverse, expr) = defaultTraverse expr + (symbolUseStart, input) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynBinding(SynBinding(expr = SynExpr.Lambda _)) + | SyntaxNode.SynBinding(SynBinding(expr = SynExpr.DotLambda _)) when skipLambdas -> None - override _.VisitBinding(_path, defaultTraverse, binding) = - match binding with - | SynBinding(expr = SynExpr.Lambda _) when skipLambdas -> defaultTraverse binding - | SynBinding(expr = SynExpr.DotLambda _) when skipLambdas -> defaultTraverse binding + // Skip manually type-annotated bindings + | SyntaxNode.SynBinding(SynBinding(returnInfo = Some(SynBindingReturnInfo _))) -> None - // Skip manually type-annotated bindings - | SynBinding(returnInfo = Some(SynBindingReturnInfo _)) -> defaultTraverse binding + // Let binding + | SyntaxNode.SynBinding(SynBinding(trivia = { EqualsRange = Some equalsRange }; range = range)) when + range.Start = symbolUseStart + -> + Some equalsRange.StartRange - // Let binding - | SynBinding(trivia = { EqualsRange = Some equalsRange }; range = range) when range.Start = symbolUseStart -> - Some equalsRange.StartRange + // Member binding + | SyntaxNode.SynBinding(SynBinding( + headPat = SynPat.LongIdent(longDotId = SynLongIdent(id = _ :: ident :: _)); trivia = { EqualsRange = Some equalsRange })) when + ident.idRange.Start = symbolUseStart + -> + Some equalsRange.StartRange - // Member binding - | SynBinding( - headPat = SynPat.LongIdent(longDotId = SynLongIdent(id = _ :: ident :: _)) - trivia = { EqualsRange = Some equalsRange }) when ident.idRange.Start = symbolUseStart -> - Some equalsRange.StartRange - - | _ -> defaultTraverse binding - } - ) + | _ -> None) member _.FindParameterLocations pos = ParameterLocations.Find(pos, input) member _.IsPositionContainedInACurriedParameter pos = - let visitor = - { new SyntaxVisitorBase<_>() with - member _.VisitExpr(_path, traverseSynExpr, defaultTraverse, expr) = defaultTraverse (expr) - - override _.VisitBinding(_path, _, binding) = - match binding with - | SynBinding(valData = valData; range = range) when rangeContainsPos range pos -> - let info = valData.SynValInfo.CurriedArgInfos - let mutable found = false - - for group in info do - for arg in group do - match arg.Ident with - | Some ident when rangeContainsPos ident.idRange pos -> found <- true - | _ -> () - - if found then Some range else None - | _ -> None - } - - let result = SyntaxTraversal.Traverse(pos, input, visitor) - result.IsSome + (pos, input) + ||> ParsedInput.exists (fun _path node -> + match node with + | SyntaxNode.SynBinding(SynBinding(valData = valData; range = range)) when rangeContainsPos range pos -> + valData.SynValInfo.CurriedArgInfos + |> List.exists ( + List.exists (function + | SynArgInfo(ident = Some ident) -> rangeContainsPos ident.idRange pos + | _ -> false) + ) + + | _ -> false) member _.IsTypeAnnotationGivenAtPosition pos = - let visitor = - { new SyntaxVisitorBase<_>() with - member _.VisitExpr(_path, _traverseSynExpr, defaultTraverse, expr) = - match expr with - | SynExpr.Typed(_expr, _typeExpr, range) when Position.posEq range.Start pos -> Some range - | _ -> defaultTraverse expr - - override _.VisitSimplePats(_path, pats) = - match pats with - | [] -> None - | _ -> - let exprFunc pat = - match pat with - // (s: string) - | SynSimplePat.Typed(_pat, _targetExpr, range) when Position.posEq range.Start pos -> Some range - | _ -> None - - pats |> List.tryPick exprFunc - - override _.VisitPat(_path, defaultTraverse, pat) = - // (s: string) - match pat with - | SynPat.Typed(_pat, _targetType, range) when Position.posEq range.Start pos -> Some range - | _ -> defaultTraverse pat + (pos, input) + ||> ParsedInput.exists (fun _path node -> + let rec (|Typed|_|) (pat: SynPat) = + if not (rangeContainsPos pat.Range pos) then + None + else + let (|AnyTyped|_|) = List.tryPick (|Typed|_|) - override _.VisitBinding(_path, defaultTraverse, binding) = - // let x : int = 12 - match binding with - | SynBinding( - headPat = SynPat.Named(range = patRange); returnInfo = Some(SynBindingReturnInfo(typeName = SynType.LongIdent _))) -> - Some patRange - | _ -> defaultTraverse binding - } + match pat with + | SynPat.Typed(range = range) when Position.posEq range.Start pos -> Some Typed + | SynPat.Paren(pat = Typed) -> Some Typed + | SynPat.Tuple(elementPats = AnyTyped) -> Some Typed + | _ -> None - let result = SyntaxTraversal.Traverse(pos, input, visitor) - result.IsSome + match node with + | SyntaxNode.SynExpr(SynExpr.Typed(range = range)) + | SyntaxNode.SynPat(SynPat.Typed(range = range)) -> Position.posEq range.Start pos + | SyntaxNode.SynTypeDefn(SynTypeDefn(implicitConstructor = Some(SynMemberDefn.ImplicitCtor(ctorArgs = Typed)))) + | SyntaxNode.SynBinding(SynBinding( + headPat = SynPat.Named _; returnInfo = Some(SynBindingReturnInfo(typeName = SynType.LongIdent _)))) -> true + | _ -> false) member _.IsPositionWithinTypeDefinition pos = - let visitor = - { new SyntaxVisitorBase<_>() with - override _.VisitComponentInfo(path, _) = - let typeDefs = - path - |> List.filter (function - | SyntaxNode.SynModule(SynModuleDecl.Types _) -> true - | _ -> false) - - match typeDefs with - | [] -> None - | _ -> Some true - } - - let result = SyntaxTraversal.Traverse(pos, input, visitor) - result.IsSome + (pos, input) + ||> ParsedInput.exists (fun _path node -> + match node with + | SyntaxNode.SynTypeDefn _ -> true + | _ -> false) member _.IsBindingALambdaAtPosition pos = - let visitor = - { new SyntaxVisitorBase<_>() with - member _.VisitExpr(_path, _traverseSynExpr, defaultTraverse, expr) = defaultTraverse expr - - override _.VisitBinding(_path, defaultTraverse, binding) = - match binding with - | SynBinding.SynBinding(expr = expr; range = range) when Position.posEq range.Start pos -> - match expr with - | SynExpr.Lambda _ -> Some range - | SynExpr.DotLambda _ -> Some range - | _ -> None - | _ -> defaultTraverse binding - } - - let result = SyntaxTraversal.Traverse(pos, input, visitor) - result.IsSome + (pos, input) + ||> ParsedInput.exists (fun _path node -> + match node with + | SyntaxNode.SynBinding(SynBinding(expr = SynExpr.Lambda _; range = range)) + | SyntaxNode.SynBinding(SynBinding(expr = SynExpr.DotLambda _; range = range)) -> Position.posEq range.Start pos + | _ -> false) member _.IsPositionWithinRecordDefinition pos = let isWithin left right middle = Position.posGt right left && Position.posLt middle right - let visitor = - { new SyntaxVisitorBase<_>() with - override _.VisitRecordDefn(_, _, range) = - if pos |> isWithin range.Start range.End then - Some true - else - None - - override _.VisitTypeAbbrev(_, synType, range) = - match synType with - | SynType.AnonRecd _ when pos |> isWithin range.Start range.End -> Some true - | _ -> None - } - - let result = SyntaxTraversal.Traverse(pos, input, visitor) - result.IsSome + (pos, input) + ||> ParsedInput.exists (fun _path node -> + match node with + | SyntaxNode.SynTypeDefn(SynTypeDefn(typeRepr = SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.Record _, range))) + | SyntaxNode.SynTypeDefn(SynTypeDefn(typeRepr = SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.TypeAbbrev _, range))) when + pos |> isWithin range.Start range.End + -> + true + | _ -> false) /// Get declared items and the selected item at the specified location member _.GetNavigationItemsImpl() = diff --git a/src/Compiler/Service/FSharpProjectSnapshot.fs b/src/Compiler/Service/FSharpProjectSnapshot.fs new file mode 100644 index 00000000000..259948dc706 --- /dev/null +++ b/src/Compiler/Service/FSharpProjectSnapshot.fs @@ -0,0 +1,626 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +module FSharp.Compiler.CodeAnalysis.ProjectSnapshot + +open System +open System.Collections.Generic +open System.IO +open System.Reflection +open FSharp.Compiler.IO +open Internal.Utilities.Library.Extras +open FSharp.Core.Printf +open FSharp.Compiler.Text + +open Internal.Utilities.Collections +open System.Threading.Tasks +open Internal.Utilities.Hashing +open System.Collections.Immutable +open System.Runtime.CompilerServices +open FSharp.Compiler.Syntax +open FSharp.Compiler.Diagnostics +open FSharp.Compiler.DiagnosticsLogger + +type internal ProjectIdentifier = string * string + +/// A common interface for an F# source file snapshot that can be used accross all stages (lazy, source loaded, parsed) +type internal IFileSnapshot = + abstract member FileName: string + abstract member Version: byte array + abstract member IsSignatureFile: bool + +[] +module internal Helpers = + + let isSignatureFile (fileName: string) = + // TODO: is this robust enough? + fileName[fileName.Length - 1] = 'i' + + let addFileName (file: IFileSnapshot) = Md5Hasher.addString file.FileName + + let addFileNameAndVersion (file: IFileSnapshot) = + addFileName file >> Md5Hasher.addBytes file.Version + + let signatureHash projectCoreVersion (sourceFiles: IFileSnapshot seq) = + let mutable lastFile = "" + + ((projectCoreVersion, Set.empty), sourceFiles) + ||> Seq.fold (fun (res, sigs) file -> + if file.IsSignatureFile then + lastFile <- file.FileName + res |> addFileNameAndVersion file, sigs |> Set.add file.FileName + else + let sigFileName = $"{file.FileName}i" + + if sigs.Contains sigFileName then + res |> addFileName file, sigs |> Set.remove sigFileName + else + lastFile <- file.FileName + res |> addFileNameAndVersion file, sigs) + |> fst, + lastFile + + let findOutputFileName options = + options + |> Seq.tryFind (fun (x: string) -> x.StartsWith("-o:")) + |> Option.map (fun x -> x.Substring(3)) + +/// A snapshot of an F# source file. +[] +type FSharpFileSnapshot(FileName: string, Version: string, GetSource: unit -> Task) = + + static member Create(fileName: string, version: string, getSource: unit -> Task) = + FSharpFileSnapshot(fileName, version, getSource) + + static member CreateFromFileSystem(fileName: string) = + FSharpFileSnapshot( + fileName, + FileSystem.GetLastWriteTimeShim(fileName).Ticks.ToString(), + fun () -> + FileSystem.OpenFileForReadShim(fileName).ReadAllText() + |> SourceTextNew.ofString + |> Task.FromResult + ) + + member public _.FileName = FileName + member _.Version = Version + member _.GetSource() = GetSource() + + member val IsSignatureFile = FileName |> isSignatureFile + + member _.GetFileName() = FileName + + override this.Equals(o) = + match o with + | :? FSharpFileSnapshot as o -> o.FileName = this.FileName && o.Version = this.Version + | _ -> false + + override this.GetHashCode() = + this.FileName.GetHashCode() + this.Version.GetHashCode() + + interface IFileSnapshot with + member this.FileName = this.FileName + member this.Version = this.Version |> System.Text.Encoding.UTF8.GetBytes + member this.IsSignatureFile = this.IsSignatureFile + +/// A source file snapshot with loaded source text. +type internal FSharpFileSnapshotWithSource + (FileName: string, SourceHash: ImmutableArray, Source: ISourceText, IsLastCompiland: bool, IsExe: bool) = + + let version = lazy (SourceHash.ToBuilder().ToArray()) + let stringVersion = lazy (version.Value |> BitConverter.ToString) + + member val Version = version.Value + member val StringVersion = stringVersion.Value + member val IsSignatureFile = FileName |> isSignatureFile + + member _.FileName = FileName + member _.Source = Source + member _.IsLastCompiland = IsLastCompiland + member _.IsExe = IsExe + + interface IFileSnapshot with + member this.FileName = this.FileName + member this.Version = this.Version + member this.IsSignatureFile = this.IsSignatureFile + +/// A source file snapshot with parsed syntax tree +type internal FSharpParsedFile + ( + FileName: string, + SyntaxTreeHash: byte array, + SourceText: ISourceText, + ParsedInput: ParsedInput, + ParseErrors: (PhasedDiagnostic * FSharpDiagnosticSeverity)[] + ) = + + member _.FileName = FileName + member _.SourceText = SourceText + member _.ParsedInput = ParsedInput + member _.ParseErrors = ParseErrors + + member val IsSignatureFile = FileName |> isSignatureFile + + interface IFileSnapshot with + member this.FileName = this.FileName + member this.Version = SyntaxTreeHash + member this.IsSignatureFile = this.IsSignatureFile + +/// An on-disk reference needed for project compilation. +[] +type ReferenceOnDisk = + { Path: string; LastModified: DateTime } + +/// A snapshot of an F# project. The source file type can differ based on which stage of compilation the snapshot is used for. +type internal ProjectSnapshotBase<'T when 'T :> IFileSnapshot>(projectCore: ProjectCore, sourceFiles: 'T list) = + + let noFileVersionsHash = + lazy + (projectCore.Version + |> Md5Hasher.addStrings (sourceFiles |> Seq.map (fun x -> x.FileName))) + + let noFileVersionsKey = + lazy + ({ new ICacheKey<_, _> with + member _.GetLabel() = projectCore.Label + member _.GetKey() = projectCore.Identifier + + member _.GetVersion() = + noFileVersionsHash.Value |> Md5Hasher.toString + + }) + + let fullHash = + lazy + (projectCore.Version + |> Md5Hasher.addStrings ( + sourceFiles + |> Seq.collect (fun x -> + seq { + x.FileName + x.Version |> Md5Hasher.toString + }) + )) + + let fullKey = + lazy + ({ new ICacheKey<_, _> with + member _.GetLabel() = projectCore.Label + member _.GetKey() = projectCore.Identifier + member _.GetVersion() = fullHash.Value |> Md5Hasher.toString + }) + + let addHash (file: 'T) hash = + hash |> Md5Hasher.addString file.FileName |> Md5Hasher.addBytes file.Version + + let signatureHash = + lazy (signatureHash projectCore.Version (sourceFiles |> Seq.map (fun x -> x :> IFileSnapshot))) + + let signatureKey = + lazy (projectCore.CacheKeyWith("Signature", signatureHash.Value |> fst |> Md5Hasher.toString)) + + let lastFileHash = + lazy + (let lastFile = sourceFiles |> List.last + let sigHash, f = signatureHash.Value + + (if f = lastFile.FileName then + sigHash + else + sigHash |> Md5Hasher.addBytes lastFile.Version), + lastFile) + + let lastFileKey = + lazy + (let hash, f = lastFileHash.Value + + { new ICacheKey<_, _> with + member _.GetLabel() = $"{f.FileName} ({projectCore.Label})" + member _.GetKey() = f.FileName, projectCore.Identifier + member _.GetVersion() = hash |> Md5Hasher.toString + }) + + let sourceFileNames = lazy (sourceFiles |> List.map (fun x -> x.FileName)) + + member _.ProjectFileName = projectCore.ProjectFileName + member _.ProjectId = projectCore.ProjectId + member _.Identifier = projectCore.Identifier + member _.ReferencesOnDisk = projectCore.ReferencesOnDisk + member _.OtherOptions = projectCore.OtherOptions + member _.ReferencedProjects = projectCore.ReferencedProjects + + member _.IsIncompleteTypeCheckEnvironment = + projectCore.IsIncompleteTypeCheckEnvironment + + member _.UseScriptResolutionRules = projectCore.UseScriptResolutionRules + member _.LoadTime = projectCore.LoadTime + member _.UnresolvedReferences = projectCore.UnresolvedReferences + member _.OriginalLoadReferences = projectCore.OriginalLoadReferences + member _.Stamp = projectCore.Stamp + member _.CommandLineOptions = projectCore.CommandLineOptions + member _.ProjectDirectory = projectCore.ProjectDirectory + + member _.OutputFileName = projectCore.OutputFileName + + member _.ProjectCore = projectCore + + member _.SourceFiles = sourceFiles + + member _.SourceFileNames = sourceFileNames.Value + + member _.Label = projectCore.Label + + member _.IndexOf fileName = + sourceFiles + |> List.tryFindIndex (fun x -> x.FileName = fileName) + |> Option.defaultWith (fun () -> failwith (sprintf "Unable to find file %s in project %s" fileName projectCore.ProjectFileName)) + + member private _.With(sourceFiles: 'T list) = + ProjectSnapshotBase(projectCore, sourceFiles) + + /// Create a new snapshot with given source files replacing files in this snapshot with the same name. Other files remain unchanged. + member this.Replace(changedSourceFiles: 'T list) = + // TODO: validate if changed files are not present in the original list? + + let sourceFiles = + sourceFiles + |> List.map (fun x -> + match changedSourceFiles |> List.tryFind (fun y -> y.FileName = x.FileName) with + | Some y -> y + | None -> x) + + this.With sourceFiles + + /// Create a new snapshot with source files only up to the given index (inclusive) + member this.UpTo fileIndex = this.With sourceFiles[..fileIndex] + + /// Create a new snapshot with source files only up to the given file name (inclusive) + member this.UpTo fileName = this.UpTo(this.IndexOf fileName) + + /// Create a new snapshot with only source files at the given indexes + member this.OnlyWith fileIndexes = + this.With( + fileIndexes + |> Set.toList + |> List.sort + |> List.choose (fun x -> sourceFiles |> List.tryItem x) + ) + + override this.ToString() = + Path.GetFileNameWithoutExtension this.ProjectFileName + |> sprintf "FSharpProjectSnapshot(%s)" + + /// The newest last modified time of any file in this snapshot including the project file + member _.GetLastModifiedTimeOnDisk() = + seq { + projectCore.ProjectFileName + + yield! + sourceFiles + |> Seq.filter (fun x -> not (x.FileName.EndsWith(".AssemblyInfo.fs"))) // TODO: is this safe? any better way of doing this? + |> Seq.filter (fun x -> not (x.FileName.EndsWith(".AssemblyAttributes.fs"))) + |> Seq.map (fun x -> x.FileName) + } + |> Seq.map FileSystem.GetLastWriteTimeShim + |> Seq.max + + member _.FullVersion = fullHash.Value + member _.SignatureVersion = signatureHash.Value |> fst + member _.LastFileVersion = lastFileHash.Value |> fst + + /// Version for parsing - doesn't include any references because they don't affect parsing (...right?) + member _.ParsingVersion = projectCore.VersionForParsing |> Md5Hasher.toString + + /// A key for this snapshot but without file versions. So it will be the same across any in-file changes. + member _.NoFileVersionsKey = noFileVersionsKey.Value + + /// A full key for this snapshot, any change will cause this to change. + member _.FullKey = fullKey.Value + + /// A key including the public surface or signature for this snapshot + member _.SignatureKey = signatureKey.Value + + /// A key including the public surface or signature for this snapshot and the last file (even if it's not a signature file) + member _.LastFileKey = lastFileKey.Value + + //TODO: cache it here? + member this.FileKey(fileName: string) = this.UpTo(fileName).LastFileKey + member this.FileKey(index: FileIndex) = this.UpTo(index).LastFileKey + +/// Project snapshot with filenames and versions given as initial input +and internal ProjectSnapshot = ProjectSnapshotBase + +/// Project snapshot with file sources loaded +and internal ProjectSnapshotWithSources = ProjectSnapshotBase + +/// All required information for compiling a project except the source files. It's kept separate so it can be reused +/// for different stages of a project snapshot and also between changes to the source files. +and internal ProjectCore + ( + ProjectFileName: string, + ProjectId: string option, + ReferencesOnDisk: ReferenceOnDisk list, + OtherOptions: string list, + ReferencedProjects: FSharpReferencedProjectSnapshot list, + IsIncompleteTypeCheckEnvironment: bool, + UseScriptResolutionRules: bool, + LoadTime: DateTime, + UnresolvedReferences: FSharpUnresolvedReferencesSet option, + OriginalLoadReferences: (range * string * string) list, + Stamp: int64 option + ) as self = + + let hashForParsing = + lazy + (Md5Hasher.empty + |> Md5Hasher.addString ProjectFileName + |> Md5Hasher.addStrings OtherOptions + |> Md5Hasher.addBool IsIncompleteTypeCheckEnvironment + |> Md5Hasher.addBool UseScriptResolutionRules) + + let fullHash = + lazy + (hashForParsing.Value + |> Md5Hasher.addStrings (ReferencesOnDisk |> Seq.map (fun r -> r.Path)) + |> Md5Hasher.addDateTimes (ReferencesOnDisk |> Seq.map (fun r -> r.LastModified)) + |> Md5Hasher.addBytes' ( + ReferencedProjects + |> Seq.map (fun (FSharpReference(_name, p)) -> p.ProjectSnapshot.SignatureVersion) + )) + + let fullHashString = lazy (fullHash.Value |> Md5Hasher.toString) + + let commandLineOptions = + lazy + (seq { + for r in ReferencesOnDisk do + $"-r:{r.Path}" + + yield! OtherOptions + } + |> Seq.toList) + + let outputFileName = lazy (OtherOptions |> findOutputFileName) + + let key = lazy (ProjectFileName, outputFileName.Value |> Option.defaultValue "") + + let cacheKey = + lazy + ({ new ICacheKey<_, _> with + member _.GetLabel() = self.Label + member _.GetKey() = self.Identifier + member _.GetVersion() = fullHashString.Value + }) + + member val ProjectDirectory = Path.GetDirectoryName(ProjectFileName) + member _.OutputFileName = outputFileName.Value + member _.Identifier: ProjectIdentifier = key.Value + member _.Version = fullHash.Value + member _.Label = ProjectFileName |> shortPath + member _.VersionForParsing = hashForParsing.Value + + member _.CommandLineOptions = commandLineOptions.Value + + member _.ProjectFileName = ProjectFileName + member _.ProjectId = ProjectId + member _.ReferencesOnDisk = ReferencesOnDisk + member _.OtherOptions = OtherOptions + member _.ReferencedProjects = ReferencedProjects + member _.IsIncompleteTypeCheckEnvironment = IsIncompleteTypeCheckEnvironment + member _.UseScriptResolutionRules = UseScriptResolutionRules + member _.LoadTime = LoadTime + member _.UnresolvedReferences = UnresolvedReferences + member _.OriginalLoadReferences = OriginalLoadReferences + member _.Stamp = Stamp + + member _.CacheKeyWith(label, version) = + { new ICacheKey<_, _> with + member _.GetLabel() = $"{label} ({self.Label})" + member _.GetKey() = self.Identifier + member _.GetVersion() = fullHashString.Value, version + } + + member _.CacheKeyWith(label, key, version) = + { new ICacheKey<_, _> with + member _.GetLabel() = $"{label} ({self.Label})" + member _.GetKey() = key, self.Identifier + member _.GetVersion() = fullHashString.Value, version + } + + member _.CacheKey = cacheKey.Value + +and [] FSharpReferencedProjectSnapshot = + | FSharpReference of projectOutputFile: string * options: FSharpProjectSnapshot + //| PEReference of projectOutputFile: string * getStamp: (unit -> DateTime) * delayedReader: DelayedILModuleReader + //| ILModuleReference of + // projectOutputFile: string * + // getStamp: (unit -> DateTime) * + // getReader: (unit -> ILModuleReader) + + /// + /// The fully qualified path to the output of the referenced project. This should be the same value as the -r + /// reference in the project options for this referenced project. + /// + member this.OutputFile = + match this with + | FSharpReference(projectOutputFile, _) -> projectOutputFile + + /// + /// Creates a reference for an F# project. The physical data for it is stored/cached inside of the compiler service. + /// + /// The fully qualified path to the output of the referenced project. This should be the same value as the -r reference in the project options for this referenced project. + /// The project snapshot for this F# project + static member CreateFSharp(projectOutputFile, snapshot: FSharpProjectSnapshot) = + FSharpReference(projectOutputFile, snapshot) + + override this.Equals(o) = + match o with + | :? FSharpReferencedProjectSnapshot as o -> + match this, o with + | FSharpReference(projectOutputFile1, options1), FSharpReference(projectOutputFile2, options2) -> + projectOutputFile1 = projectOutputFile2 && options1 = options2 + + | _ -> false + + override this.GetHashCode() = this.OutputFile.GetHashCode() + +/// An identifier of an F# project. This serves to identify the same project as it changes over time and enables us to clear obsolete data from caches. +and [] FSharpProjectIdentifier = + | FSharpProjectIdentifier of projectFileName: string * outputFileName: string + +/// A snapshot of an F# project. This type contains all the necessary information for type checking a project. +and [] FSharpProjectSnapshot internal (projectSnapshot) = + + member internal _.ProjectSnapshot: ProjectSnapshot = projectSnapshot + + /// Create a new snapshot with given source files replacing files in this snapshot with the same name. Other files remain unchanged. + member _.Replace(changedSourceFiles: FSharpFileSnapshot list) = + projectSnapshot.Replace(changedSourceFiles) |> FSharpProjectSnapshot + + member _.Label = projectSnapshot.Label + member _.Identifier = FSharpProjectIdentifier projectSnapshot.ProjectCore.Identifier + + static member Create + ( + projectFileName: string, + projectId: string option, + sourceFiles: FSharpFileSnapshot list, + referencesOnDisk: ReferenceOnDisk list, + otherOptions: string list, + referencedProjects: FSharpReferencedProjectSnapshot list, + isIncompleteTypeCheckEnvironment: bool, + useScriptResolutionRules: bool, + loadTime: DateTime, + unresolvedReferences: FSharpUnresolvedReferencesSet option, + originalLoadReferences: (range * string * string) list, + stamp: int64 option + ) = + + let projectCore = + ProjectCore( + projectFileName, + projectId, + referencesOnDisk, + otherOptions, + referencedProjects, + isIncompleteTypeCheckEnvironment, + useScriptResolutionRules, + loadTime, + unresolvedReferences, + originalLoadReferences, + stamp + ) + + ProjectSnapshotBase(projectCore, sourceFiles) |> FSharpProjectSnapshot + + static member FromOptions(options: FSharpProjectOptions, getFileSnapshot, ?snapshotAccumulator) = + let snapshotAccumulator = defaultArg snapshotAccumulator (Dictionary()) + + async { + + // TODO: check if options is a good key here + if not (snapshotAccumulator.ContainsKey options) then + + let! sourceFiles = options.SourceFiles |> Seq.map (getFileSnapshot options) |> Async.Parallel + + let! referencedProjects = + options.ReferencedProjects + |> Seq.choose (function + | FSharpReferencedProject.FSharpReference(outputName, options) -> + Some( + async { + let! snapshot = FSharpProjectSnapshot.FromOptions(options, getFileSnapshot, snapshotAccumulator) + + return FSharpReferencedProjectSnapshot.FSharpReference(outputName, snapshot) + } + ) + // TODO: other types + | _ -> None) + |> Async.Sequential + + let referencesOnDisk, otherOptions = + options.OtherOptions + |> Array.partition (fun x -> x.StartsWith("-r:")) + |> map1Of2 ( + Array.map (fun x -> + let path = x.Substring(3) + + { + Path = path + LastModified = FileSystem.GetLastWriteTimeShim(path) + }) + ) + + let snapshot = + FSharpProjectSnapshot.Create( + projectFileName = options.ProjectFileName, + projectId = options.ProjectId, + sourceFiles = (sourceFiles |> List.ofArray), + referencesOnDisk = (referencesOnDisk |> List.ofArray), + otherOptions = (otherOptions |> List.ofArray), + referencedProjects = (referencedProjects |> List.ofArray), + isIncompleteTypeCheckEnvironment = options.IsIncompleteTypeCheckEnvironment, + useScriptResolutionRules = options.UseScriptResolutionRules, + loadTime = options.LoadTime, + unresolvedReferences = options.UnresolvedReferences, + originalLoadReferences = options.OriginalLoadReferences, + stamp = options.Stamp + ) + + snapshotAccumulator.Add(options, snapshot) + + return snapshotAccumulator[options] + } + + static member internal GetFileSnapshotFromDisk _ fileName = + FSharpFileSnapshot.CreateFromFileSystem fileName |> async.Return + + static member FromOptions(options: FSharpProjectOptions) = + FSharpProjectSnapshot.FromOptions(options, FSharpProjectSnapshot.GetFileSnapshotFromDisk) + + static member FromOptions(options: FSharpProjectOptions, fileName: string, fileVersion: int, sourceText: ISourceText) = + + let getFileSnapshot _ fName = + if fName = fileName then + FSharpFileSnapshot.Create( + fileName, + $"{fileVersion}{sourceText.GetHashCode().ToString()}", + fun () -> Task.FromResult(SourceTextNew.ofISourceText sourceText) + ) + else + FSharpFileSnapshot.CreateFromFileSystem fName + |> async.Return + + FSharpProjectSnapshot.FromOptions(options, getFileSnapshot) + +let rec internal snapshotToOptions (projectSnapshot: ProjectSnapshotBase<_>) = + { + ProjectFileName = projectSnapshot.ProjectFileName + ProjectId = projectSnapshot.ProjectId + SourceFiles = projectSnapshot.SourceFiles |> Seq.map (fun x -> x.FileName) |> Seq.toArray + OtherOptions = projectSnapshot.CommandLineOptions |> List.toArray + ReferencedProjects = + projectSnapshot.ReferencedProjects + |> Seq.map (function + | FSharpReference(name, opts) -> FSharpReferencedProject.FSharpReference(name, opts.ProjectSnapshot |> snapshotToOptions)) + |> Seq.toArray + IsIncompleteTypeCheckEnvironment = projectSnapshot.IsIncompleteTypeCheckEnvironment + UseScriptResolutionRules = projectSnapshot.UseScriptResolutionRules + LoadTime = projectSnapshot.LoadTime + UnresolvedReferences = projectSnapshot.UnresolvedReferences + OriginalLoadReferences = projectSnapshot.OriginalLoadReferences + Stamp = projectSnapshot.Stamp + } + +[] +type internal Extensions = + + [] + static member ToOptions(this: ProjectSnapshot) = this |> snapshotToOptions + + [] + static member ToOptions(this: FSharpProjectSnapshot) = + this.ProjectSnapshot |> snapshotToOptions + + [] + static member GetProjectIdentifier(this: FSharpProjectOptions) : ProjectIdentifier = + this.ProjectFileName, this.OtherOptions |> findOutputFileName |> Option.defaultValue "" diff --git a/src/Compiler/Service/IncrementalBuild.fs b/src/Compiler/Service/IncrementalBuild.fs index d37cd97671a..279de60274f 100644 --- a/src/Compiler/Service/IncrementalBuild.fs +++ b/src/Compiler/Service/IncrementalBuild.fs @@ -485,10 +485,19 @@ type BoundModel private ( syntaxTreeOpt ) - /// Global service state -type FrameworkImportsCacheKey = FrameworkImportsCacheKey of resolvedpath: string list * assemblyName: string * targetFrameworkDirectories: string list * fsharpBinaries: string * langVersion: decimal +type FrameworkImportsCacheKey = + | FrameworkImportsCacheKey of resolvedpath: string list * assemblyName: string * targetFrameworkDirectories: string list * fsharpBinaries: string * langVersion: decimal + + interface ICacheKey with + member this.GetKey() = + this |> function FrameworkImportsCacheKey(assemblyName=a) -> a + member this.GetLabel() = + this |> function FrameworkImportsCacheKey(assemblyName=a) -> a + + member this.GetVersion() = this + /// Represents a cache of 'framework' references that can be shared between multiple incremental builds type FrameworkImportsCache(size) = @@ -593,6 +602,7 @@ module Utilities = /// Constructs the build data (IRawFSharpAssemblyData) representing the assembly when used /// as a cross-assembly reference. Note the assembly has not been generated on disk, so this is /// a virtualized view of the assembly contents as computed by background checking. +[] type RawFSharpAssemblyDataBackedByLanguageService (tcConfig, tcGlobals, generatedCcu: CcuThunk, outfile, topAttrs, assemblyName, ilAssemRef) = let exportRemapping = MakeExportRemapping generatedCcu generatedCcu.Contents diff --git a/src/Compiler/Service/IncrementalBuild.fsi b/src/Compiler/Service/IncrementalBuild.fsi index b4e60d403f0..0dedfb02948 100644 --- a/src/Compiler/Service/IncrementalBuild.fsi +++ b/src/Compiler/Service/IncrementalBuild.fsi @@ -22,6 +22,17 @@ open FSharp.Compiler.TcGlobals open FSharp.Compiler.Text open FSharp.Compiler.TypedTree open FSharp.Compiler.BuildGraph +open Internal.Utilities.Collections + +type internal FrameworkImportsCacheKey = + | FrameworkImportsCacheKey of + resolvedpath: string list * + assemblyName: string * + targetFrameworkDirectories: string list * + fsharpBinaries: string * + langVersion: decimal + + interface ICacheKey /// Lookup the global static cache for building the FrameworkTcImports type internal FrameworkImportsCache = @@ -132,6 +143,20 @@ type internal PartialCheckResults = member TimeStamp: DateTime +[] +type internal RawFSharpAssemblyDataBackedByLanguageService = + new: + tcConfig: TcConfig * + tcGlobals: TcGlobals * + generatedCcu: CcuThunk * + outfile: string * + topAttrs: TopAttribs * + assemblyName: string * + ilAssemRef: FSharp.Compiler.AbstractIL.IL.ILAssemblyRef -> + RawFSharpAssemblyDataBackedByLanguageService + + interface IRawFSharpAssemblyData + /// Manages an incremental build graph for the build of an F# project [] type internal IncrementalBuilder = diff --git a/src/Compiler/Service/ItemKey.fs b/src/Compiler/Service/ItemKey.fs index daf6a28f544..7a904a235ed 100644 --- a/src/Compiler/Service/ItemKey.fs +++ b/src/Compiler/Service/ItemKey.fs @@ -562,7 +562,6 @@ and [] ItemKeyStoreBuilder(tcGlobals: TcGlobals) = // We should consider writing ItemKey for each of these | Item.OtherName _ -> () - | Item.FakeInterfaceCtor _ -> () | Item.CustomOperation _ -> () | Item.CustomBuilder _ -> () | Item.ImplicitOp _ -> () diff --git a/src/Compiler/Service/SemanticClassification.fs b/src/Compiler/Service/SemanticClassification.fs index 3697d781373..6ebbb3c8ae0 100644 --- a/src/Compiler/Service/SemanticClassification.fs +++ b/src/Compiler/Service/SemanticClassification.fs @@ -75,7 +75,7 @@ module TcResolutionsExtensions = && protectAssemblyExplorationNoReraise false false (fun () -> ExistsHeadTypeInEntireHierarchy g amap range0 ty g.tcref_System_IDisposable) - let isDiscard (str: string) = str.StartsWith("_") + let isDiscard (str: string) = str.StartsWithOrdinal("_") let isValRefDisposable g amap (vref: ValRef) = not (isDiscard vref.DisplayName) @@ -287,8 +287,6 @@ module TcResolutionsExtensions = | Item.DelegateCtor _, _, m -> add m SemanticClassificationType.ConstructorForReferenceType - | Item.FakeInterfaceCtor _, _, m -> add m SemanticClassificationType.ConstructorForReferenceType - | Item.MethodGroup(_, minfos, _), _, m -> match minfos with | [] -> add m SemanticClassificationType.Method diff --git a/src/Compiler/Service/ServiceAnalysis.fs b/src/Compiler/Service/ServiceAnalysis.fs index 777a9678769..29df63b1194 100644 --- a/src/Compiler/Service/ServiceAnalysis.fs +++ b/src/Compiler/Service/ServiceAnalysis.fs @@ -2,12 +2,12 @@ namespace FSharp.Compiler.EditorServices +open System open System.Collections.Generic open System.Runtime.CompilerServices open Internal.Utilities.Library open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.Symbols -open FSharp.Compiler.Syntax open FSharp.Compiler.Syntax.PrettyNaming open FSharp.Compiler.Text open FSharp.Compiler.Text.Range @@ -296,12 +296,19 @@ module UnusedOpens = /// Async to allow cancellation. let getUnusedOpens (checkFileResults: FSharpCheckFileResults, getSourceLineStr: int -> string) : Async = async { - let! ct = Async.CancellationToken - let symbolUses = checkFileResults.GetAllUsesOfAllSymbolsInFile(ct) - let symbolUses = filterSymbolUses getSourceLineStr symbolUses - let symbolUses = splitSymbolUses symbolUses - let openStatements = getOpenStatements checkFileResults.OpenDeclarations - return! filterOpenStatements symbolUses openStatements + if checkFileResults.OpenDeclarations.Length = 0 then + return [] + else + let! ct = Async.CancellationToken + let symbolUses = checkFileResults.GetAllUsesOfAllSymbolsInFile(ct) + let symbolUses = filterSymbolUses getSourceLineStr symbolUses + let symbolUses = splitSymbolUses symbolUses + let openStatements = getOpenStatements checkFileResults.OpenDeclarations + + if openStatements.Length = 0 then + return [] + else + return! filterOpenStatements symbolUses openStatements } module SimplifyNames = @@ -332,7 +339,10 @@ module SimplifyNames = - partialName.PartialIdent.Length - (getPlidLength partialName.QualifyingIdents) - if partialName.PartialIdent = "" || List.isEmpty partialName.QualifyingIdents then + if + String.IsNullOrEmpty(partialName.PartialIdent) + || List.isEmpty partialName.QualifyingIdents + then None else Some(symbolUse, partialName.QualifyingIdents, plidStartCol, partialName.PartialIdent)) @@ -435,7 +445,7 @@ module UnusedDeclarations = su.IsFromDefinition && su.Symbol.DeclarationLocation.IsSome && (isScript || su.IsPrivateToFile) - && not (su.Symbol.DisplayName.StartsWith "_") + && not (su.Symbol.DisplayName.StartsWithOrdinal "_") && isPotentiallyUnusedDeclaration su.Symbol then Some(su, usages.Contains su.Symbol.DeclarationLocation.Value) @@ -452,1273 +462,3 @@ module UnusedDeclarations = let unusedRanges = getUnusedDeclarationRanges allSymbolUsesInFile isScriptFile return unusedRanges } - -module UnnecessaryParentheses = - open System - - let (|Ident|) (ident: Ident) = ident.idText - - /// Represents an expression's precedence, or, - /// for a few few types of expression whose exact - /// kind can be significant, the expression's exact kind. - /// - /// Use Precedence.sameKind to determine whether two expressions - /// have the same kind. Use Precedence.compare to compare two - /// expressions' precedence. Avoid using relational operators or the - /// built-in compare function on this type. - type Precedence = - /// yield, yield!, return, return! - | Low - - /// <- - | Set - - /// := - | ColonEquals - - /// , - | Comma - - /// or, || - /// - /// Refers to the exact operators or and ||. - /// Instances with leading dots or question marks or trailing characters are parsed as Bar instead. - | BarBar - - /// &, && - /// - /// Refers to the exact operators & and &&. - /// Instances with leading dots or question marks or trailing characters are parsed as Amp instead. - | AmpAmp - - /// :?> - | Downcast - - /// :> - | Upcast - - /// =… - | Eq - - /// |… - | Bar - - /// &… - | Amp - - /// $… - | Dollar - - /// >… - | Greater - - /// <… - | Less - - /// !=… - | BangEq - - /// ^… - | Hat - - /// @… - | At - - /// :: - | Cons - - /// :? - | TypeTest - - /// -… - | Sub - - /// +… - | Add - - /// %… - | Mod - - /// /… - | Div - - /// *… - | Mul - - /// **… - | Exp - - /// - x - | UnaryPrefix - - /// f x - | Apply - - /// -x, !… x, ~~… x - | High - - // x.y - | Dot - - module Precedence = - /// Returns true only if the two expressions are of the - /// exact same kind. E.g., Add = Add and Sub = Sub, - /// but Add <> Sub, even though their precedence compares equally. - let sameKind prec1 prec2 = prec1 = prec2 - - /// Compares two expressions' precedence. - let compare prec1 prec2 = - match prec1, prec2 with - | Dot, Dot -> 0 - | Dot, _ -> 1 - | _, Dot -> -1 - - | High, High -> 0 - | High, _ -> 1 - | _, High -> -1 - - | Apply, Apply -> 0 - | Apply, _ -> 1 - | _, Apply -> -1 - - | UnaryPrefix, UnaryPrefix -> 0 - | UnaryPrefix, _ -> 1 - | _, UnaryPrefix -> -1 - - | Exp, Exp -> 0 - | Exp, _ -> 1 - | _, Exp -> -1 - - | (Mod | Div | Mul), (Mod | Div | Mul) -> 0 - | (Mod | Div | Mul), _ -> 1 - | _, (Mod | Div | Mul) -> -1 - - | (Sub | Add), (Sub | Add) -> 0 - | (Sub | Add), _ -> 1 - | _, (Sub | Add) -> -1 - - | TypeTest, TypeTest -> 0 - | TypeTest, _ -> 1 - | _, TypeTest -> -1 - - | Cons, Cons -> 0 - | Cons, _ -> 1 - | _, Cons -> -1 - - | (Hat | At), (Hat | At) -> 0 - | (Hat | At), _ -> 1 - | _, (Hat | At) -> -1 - - | (Eq | Bar | Amp | Dollar | Greater | Less | BangEq), (Eq | Bar | Amp | Dollar | Greater | Less | BangEq) -> 0 - | (Eq | Bar | Amp | Dollar | Greater | Less | BangEq), _ -> 1 - | _, (Eq | Bar | Amp | Dollar | Greater | Less | BangEq) -> -1 - - | (Downcast | Upcast), (Downcast | Upcast) -> 0 - | (Downcast | Upcast), _ -> 1 - | _, (Downcast | Upcast) -> -1 - - | AmpAmp, AmpAmp -> 0 - | AmpAmp, _ -> 1 - | _, AmpAmp -> -1 - - | BarBar, BarBar -> 0 - | BarBar, _ -> 1 - | _, BarBar -> -1 - - | Comma, Comma -> 0 - | Comma, _ -> 1 - | _, Comma -> -1 - - | ColonEquals, ColonEquals -> 0 - | ColonEquals, _ -> 1 - | _, ColonEquals -> -1 - - | Set, Set -> 0 - | Set, _ -> 1 - | _, Set -> -1 - - | Low, Low -> 0 - - /// Associativity/association. - type Assoc = - /// Non-associative or no association. - | Non - - /// Left-associative or left-hand association. - | Left - - /// Right-associative or right-hand association. - | Right - - module Assoc = - let ofPrecedence precedence = - match precedence with - | Low -> Non - | Set -> Non - | ColonEquals -> Right - | Comma -> Non - | BarBar -> Left - | AmpAmp -> Left - | Upcast - | Downcast -> Right - | Eq - | Bar - | Amp - | Dollar - | Greater - | Less - | BangEq -> Left - | At - | Hat -> Right - | Cons -> Right - | TypeTest -> Non - | Add - | Sub -> Left - | Mul - | Div - | Mod -> Left - | Exp -> Right - | UnaryPrefix -> Left - | Apply -> Left - | High -> Left - | Dot -> Left - - /// Matches if the two expressions or patterns refer to the same object. - [] - let inline (|Is|_|) (inner1: 'a) (inner2: 'a) = - if obj.ReferenceEquals(inner1, inner2) then - ValueSome Is - else - ValueNone - - module SynExpr = - open FSharp.Compiler.SyntaxTrivia - - /// See atomicExprAfterType in pars.fsy. - [] - let (|AtomicExprAfterType|_|) expr = - match expr with - | SynExpr.Paren _ - | SynExpr.Quote _ - | SynExpr.Const _ - | SynExpr.Tuple(isStruct = true) - | SynExpr.Record _ - | SynExpr.AnonRecd _ - | SynExpr.InterpolatedString _ - | SynExpr.Null _ - | SynExpr.ArrayOrList(isArray = true) - | SynExpr.ArrayOrListComputed(isArray = true) -> ValueSome AtomicExprAfterType - | _ -> ValueNone - - /// Matches if the given expression represents a high-precedence - /// function application, e.g., - /// - /// f x - /// - /// (+) x y - [] - let (|HighPrecedenceApp|_|) expr = - match expr with - | SynExpr.App(isInfix = false; funcExpr = SynExpr.Ident _) - | SynExpr.App(isInfix = false; funcExpr = SynExpr.LongIdent _) - | SynExpr.App(isInfix = false; funcExpr = SynExpr.App(isInfix = false)) -> ValueSome HighPrecedenceApp - | _ -> ValueNone - - module FuncExpr = - /// Matches when the given funcExpr is a direct application - /// of a symbolic operator, e.g., -, _not_ (~-). - [] - let (|SymbolicOperator|_|) funcExpr = - match funcExpr with - | SynExpr.LongIdent(longDotId = SynLongIdent(trivia = trivia)) -> - let rec tryPick = - function - | [] -> ValueNone - | Some(IdentTrivia.OriginalNotation op) :: _ -> ValueSome op - | _ :: rest -> tryPick rest - - tryPick trivia - | _ -> ValueNone - - /// Matches when the given expression is a prefix operator application, e.g., - /// - /// -x - /// - /// ~~~x - [] - let (|PrefixApp|_|) expr : Precedence voption = - match expr with - | SynExpr.App(isInfix = false; funcExpr = funcExpr & FuncExpr.SymbolicOperator op; argExpr = argExpr) -> - if funcExpr.Range.IsAdjacentTo argExpr.Range then - ValueSome High - else - assert (op.Length > 0) - - match op[0] with - | '!' - | '~' -> ValueSome High - | _ -> ValueSome UnaryPrefix - - | SynExpr.AddressOf(expr = expr; opRange = opRange) -> - if opRange.IsAdjacentTo expr.Range then - ValueSome High - else - ValueSome UnaryPrefix - - | _ -> ValueNone - - /// Tries to parse the given original notation as a symbolic infix operator. - [] - let (|SymbolPrec|_|) (originalNotation: string) = - // Trim any leading dots or question marks from the given symbolic operator. - // Leading dots or question marks have no effect on operator precedence or associativity - // with the exception of &, &&, and ||. - let ignoredLeadingChars = ".?".AsSpan() - let trimmed = originalNotation.AsSpan().TrimStart ignoredLeadingChars - assert (trimmed.Length > 0) - - match trimmed[0], originalNotation with - | _, ":=" -> ValueSome ColonEquals - | _, ("||" | "or") -> ValueSome BarBar - | _, ("&" | "&&") -> ValueSome AmpAmp - | '|', _ -> ValueSome Bar - | '&', _ -> ValueSome Amp - | '<', _ -> ValueSome Less - | '>', _ -> ValueSome Greater - | '=', _ -> ValueSome Eq - | '$', _ -> ValueSome Dollar - | '!', _ when trimmed.Length > 1 && trimmed[1] = '=' -> ValueSome BangEq - | '^', _ -> ValueSome Hat - | '@', _ -> ValueSome At - | _, "::" -> ValueSome Cons - | '+', _ -> ValueSome Add - | '-', _ -> ValueSome Sub - | '/', _ -> ValueSome Div - | '%', _ -> ValueSome Mod - | '*', _ when trimmed.Length > 1 && trimmed[1] = '*' -> ValueSome Exp - | '*', _ -> ValueSome Mul - | _ -> ValueNone - - /// Any expressions in which the removal of parens would - /// lead to something like the following that would be - /// confused by the parser with a type parameter application: - /// - /// xz - /// - /// xz - [] - let rec (|ConfusableWithTypeApp|_|) synExpr = - match synExpr with - | SynExpr.Paren(expr = ConfusableWithTypeApp) - | SynExpr.App(funcExpr = ConfusableWithTypeApp) - | SynExpr.App(isInfix = true; funcExpr = FuncExpr.SymbolicOperator(SymbolPrec Greater); argExpr = ConfusableWithTypeApp) -> - ValueSome ConfusableWithTypeApp - | SynExpr.App(isInfix = true; funcExpr = funcExpr & FuncExpr.SymbolicOperator(SymbolPrec Less); argExpr = argExpr) when - argExpr.Range.IsAdjacentTo funcExpr.Range - -> - ValueSome ConfusableWithTypeApp - | SynExpr.Tuple(exprs = exprs) -> - let rec anyButLast = - function - | _ :: [] - | [] -> ValueNone - | ConfusableWithTypeApp :: _ -> ValueSome ConfusableWithTypeApp - | _ :: tail -> anyButLast tail - - anyButLast exprs - | _ -> ValueNone - - /// Matches when the expression represents the infix application of a symbolic operator. - /// - /// (x λ y) ρ z - /// - /// x λ (y ρ z) - [] - let (|InfixApp|_|) synExpr : struct (Precedence * Assoc) voption = - match synExpr with - | SynExpr.App(funcExpr = SynExpr.App(isInfix = true; funcExpr = FuncExpr.SymbolicOperator(SymbolPrec prec))) -> - ValueSome(prec, Right) - | SynExpr.App(isInfix = true; funcExpr = FuncExpr.SymbolicOperator(SymbolPrec prec)) -> ValueSome(prec, Left) - | SynExpr.Upcast _ -> ValueSome(Upcast, Left) - | SynExpr.Downcast _ -> ValueSome(Downcast, Left) - | SynExpr.TypeTest _ -> ValueSome(TypeTest, Left) - | _ -> ValueNone - - /// Returns the given expression's precedence and the side of the inner expression, - /// if applicable. - [] - let (|OuterBinaryExpr|_|) inner outer : struct (Precedence * Assoc) voption = - match outer with - | SynExpr.YieldOrReturn _ - | SynExpr.YieldOrReturnFrom _ -> ValueSome(Low, Right) - | SynExpr.Tuple(exprs = SynExpr.Paren(expr = Is inner) :: _) -> ValueSome(Comma, Left) - | SynExpr.Tuple _ -> ValueSome(Comma, Right) - | InfixApp(Cons, side) -> ValueSome(Cons, side) - | SynExpr.Assert _ - | SynExpr.Lazy _ - | SynExpr.InferredUpcast _ - | SynExpr.InferredDowncast _ -> ValueSome(Apply, Non) - | PrefixApp prec -> ValueSome(prec, Non) - | InfixApp(prec, side) -> ValueSome(prec, side) - | SynExpr.App(argExpr = SynExpr.ComputationExpr _) -> ValueSome(UnaryPrefix, Left) - | SynExpr.App(funcExpr = SynExpr.Paren(expr = SynExpr.App _)) -> ValueSome(Apply, Left) - | SynExpr.App _ -> ValueSome(Apply, Non) - | SynExpr.DotSet(targetExpr = SynExpr.Paren(expr = Is inner)) -> ValueSome(Dot, Left) - | SynExpr.DotSet(rhsExpr = SynExpr.Paren(expr = Is inner)) -> ValueSome(Set, Right) - | SynExpr.DotIndexedSet(objectExpr = SynExpr.Paren(expr = Is inner)) - | SynExpr.DotNamedIndexedPropertySet(targetExpr = SynExpr.Paren(expr = Is inner)) -> ValueSome(Dot, Left) - | SynExpr.DotIndexedSet(valueExpr = SynExpr.Paren(expr = Is inner)) - | SynExpr.DotNamedIndexedPropertySet(rhsExpr = SynExpr.Paren(expr = Is inner)) -> ValueSome(Set, Right) - | SynExpr.LongIdentSet(expr = SynExpr.Paren(expr = Is inner)) -> ValueSome(Set, Right) - | SynExpr.Set _ -> ValueSome(Set, Non) - | SynExpr.DotGet _ -> ValueSome(Dot, Left) - | SynExpr.DotIndexedGet(objectExpr = SynExpr.Paren(expr = Is inner)) -> ValueSome(Dot, Left) - | _ -> ValueNone - - /// Matches a SynExpr.App nested in a sequence of dot-gets. - /// - /// x.M.N().O - [] - let (|NestedApp|_|) expr = - let rec loop = - function - | SynExpr.DotGet(expr = expr) - | SynExpr.DotIndexedGet(objectExpr = expr) -> loop expr - | SynExpr.App _ -> ValueSome NestedApp - | _ -> ValueNone - - loop expr - - /// Returns the given expression's precedence, if applicable. - [] - let (|InnerBinaryExpr|_|) expr : Precedence voption = - match expr with - | SynExpr.Tuple(isStruct = false) -> ValueSome Comma - | SynExpr.DotGet(expr = NestedApp) - | SynExpr.DotIndexedGet(objectExpr = NestedApp) -> ValueSome Apply - | SynExpr.DotGet _ - | SynExpr.DotIndexedGet _ -> ValueSome Dot - | PrefixApp prec -> ValueSome prec - | InfixApp(prec, _) -> ValueSome prec - | SynExpr.App _ - | SynExpr.Assert _ - | SynExpr.Lazy _ - | SynExpr.For _ - | SynExpr.ForEach _ - | SynExpr.While _ - | SynExpr.Do _ - | SynExpr.New _ - | SynExpr.InferredUpcast _ - | SynExpr.InferredDowncast _ -> ValueSome Apply - | SynExpr.DotIndexedSet _ - | SynExpr.DotNamedIndexedPropertySet _ - | SynExpr.DotSet _ -> ValueSome Set - | _ -> ValueNone - - module Dangling = - /// Returns the first matching nested right-hand target expression, if any. - let private dangling (target: SynExpr -> SynExpr option) = - let (|Target|_|) = target - let (|Last|) = List.last - - let rec loop expr = - match expr with - | Target expr -> ValueSome expr - | SynExpr.Tuple(isStruct = false; exprs = Last expr) - | SynExpr.App(argExpr = expr) - | SynExpr.IfThenElse(elseExpr = Some expr) - | SynExpr.IfThenElse(ifExpr = expr) - | SynExpr.Sequential(expr2 = expr) - | SynExpr.YieldOrReturn(expr = expr) - | SynExpr.YieldOrReturnFrom(expr = expr) - | SynExpr.Set(rhsExpr = expr) - | SynExpr.DotSet(rhsExpr = expr) - | SynExpr.DotNamedIndexedPropertySet(rhsExpr = expr) - | SynExpr.DotIndexedSet(valueExpr = expr) - | SynExpr.LongIdentSet(expr = expr) - | SynExpr.LetOrUse(body = expr) - | SynExpr.Lambda(body = expr) - | SynExpr.Match(clauses = Last(SynMatchClause(resultExpr = expr))) - | SynExpr.MatchLambda(matchClauses = Last(SynMatchClause(resultExpr = expr))) - | SynExpr.MatchBang(clauses = Last(SynMatchClause(resultExpr = expr))) - | SynExpr.TryWith(withCases = Last(SynMatchClause(resultExpr = expr))) - | SynExpr.TryFinally(finallyExpr = expr) -> loop expr - | _ -> ValueNone - - loop - - /// Matches a dangling if-then construct. - [] - let (|IfThen|_|) = - dangling (function - | SynExpr.IfThenElse _ as expr -> Some expr - | _ -> None) - - /// Matches a dangling sequential expression. - [] - let (|Sequential|_|) = - dangling (function - | SynExpr.Sequential _ as expr -> Some expr - | _ -> None) - - /// Matches a dangling try-with or try-finally construct. - [] - let (|Try|_|) = - dangling (function - | SynExpr.TryWith _ - | SynExpr.TryFinally _ as expr -> Some expr - | _ -> None) - - /// Matches a dangling match-like construct. - [] - let (|Match|_|) = - dangling (function - | SynExpr.Match _ - | SynExpr.MatchBang _ - | SynExpr.MatchLambda _ - | SynExpr.TryWith _ - | SynExpr.Lambda _ as expr -> Some expr - | _ -> None) - - /// Matches a nested dangling construct that could become problematic - /// if the surrounding parens were removed. - [] - let (|Problematic|_|) = - dangling (function - | SynExpr.Lambda _ - | SynExpr.MatchLambda _ - | SynExpr.Match _ - | SynExpr.MatchBang _ - | SynExpr.TryWith _ - | SynExpr.TryFinally _ - | SynExpr.IfThenElse _ - | SynExpr.Sequential _ - | SynExpr.LetOrUse _ - | SynExpr.Set _ - | SynExpr.LongIdentSet _ - | SynExpr.DotIndexedSet _ - | SynExpr.DotNamedIndexedPropertySet _ - | SynExpr.DotSet _ - | SynExpr.NamedIndexedPropertySet _ as expr -> Some expr - | _ -> None) - - /// If the given expression is a parenthesized expression and the parentheses - /// are unnecessary in the given context, returns the unnecessary parentheses' range. - let rec unnecessaryParentheses (getSourceLineStr: int -> string) expr path = - let unnecessaryParentheses = unnecessaryParentheses getSourceLineStr - - // Indicates whether the parentheses with the given range - // enclose an expression whose indentation would be invalid - // in context if it were not surrounded by parentheses. - let containsSensitiveIndentation outerOffsides (parenRange: range) = - let startLine = parenRange.StartLine - let endLine = parenRange.EndLine - - if startLine = endLine then - false - else - let rec loop offsides lineNo startCol = - if lineNo <= endLine then - let line = getSourceLineStr lineNo - - match offsides with - | ValueNone -> - let i = line.AsSpan(startCol).IndexOfAnyExcept(' ', ')') - - if i >= 0 then - let newOffsides = i + startCol - newOffsides <= outerOffsides || loop (ValueSome newOffsides) (lineNo + 1) 0 - else - loop offsides (lineNo + 1) 0 - - | ValueSome offsidesCol -> - let i = line.AsSpan(0, min offsidesCol line.Length).IndexOfAnyExcept(' ', ')') - - if i >= 0 && i < offsidesCol then - let slice = line.AsSpan(i, min (offsidesCol - i) (line.Length - i)) - let j = slice.IndexOfAnyExcept("*/%-+:^@><=!|0$.?".AsSpan()) - - let lo = i + (if j >= 0 && slice[j] = ' ' then j else 0) - lo < offsidesCol - 1 || lo <= outerOffsides || loop offsides (lineNo + 1) 0 - else - loop offsides (lineNo + 1) 0 - else - false - - loop ValueNone startLine (parenRange.StartColumn + 1) - - // Matches if the given expression starts with a symbol, e.g., <@ … @>, $"…", @"…", +1, -1… - let (|StartsWithSymbol|_|) = - let (|TextStartsWith|) (m: range) = - let line = getSourceLineStr m.StartLine - line[m.StartColumn] - - let (|StartsWith|) (s: string) = s[0] - - function - | SynExpr.Quote _ - | SynExpr.InterpolatedString _ - | SynExpr.Const(SynConst.String(synStringKind = SynStringKind.Verbatim), _) - | SynExpr.Const(SynConst.Byte _, TextStartsWith '+') - | SynExpr.Const(SynConst.UInt16 _, TextStartsWith '+') - | SynExpr.Const(SynConst.UInt32 _, TextStartsWith '+') - | SynExpr.Const(SynConst.UInt64 _, TextStartsWith '+') - | SynExpr.Const(SynConst.UIntPtr _, TextStartsWith '+') - | SynExpr.Const(SynConst.SByte _, TextStartsWith('-' | '+')) - | SynExpr.Const(SynConst.Int16 _, TextStartsWith('-' | '+')) - | SynExpr.Const(SynConst.Int32 _, TextStartsWith('-' | '+')) - | SynExpr.Const(SynConst.Int64 _, TextStartsWith('-' | '+')) - | SynExpr.Const(SynConst.IntPtr _, TextStartsWith('-' | '+')) - | SynExpr.Const(SynConst.Decimal _, TextStartsWith('-' | '+')) - | SynExpr.Const(SynConst.Double _, TextStartsWith('-' | '+')) - | SynExpr.Const(SynConst.Single _, TextStartsWith('-' | '+')) - | SynExpr.Const(SynConst.Measure(_, TextStartsWith('-' | '+'), _, _), _) - | SynExpr.Const(SynConst.UserNum(StartsWith('-' | '+'), _), _) -> Some StartsWithSymbol - | _ -> None - - // Matches if the given expression is a numeric literal - // that it is safe to "dot into," e.g., 1l, 0b1, 1e10, 1d, 1.0… - let (|DotSafeNumericLiteral|_|) = - /// 1l, 1d, 0b1, 0x1, 0o1, 1e10… - let (|TextContainsLetter|_|) (m: range) = - let line = getSourceLineStr m.StartLine - let span = line.AsSpan(m.StartColumn, m.EndColumn - m.StartColumn) - - if span.LastIndexOfAnyInRange('A', 'z') >= 0 then - Some TextContainsLetter - else - None - - // 1.0… - let (|TextEndsWithNumber|_|) (m: range) = - let line = getSourceLineStr m.StartLine - let span = line.AsSpan(m.StartColumn, m.EndColumn - m.StartColumn) - - if Char.IsDigit span[span.Length - 1] then - Some TextEndsWithNumber - else - None - - function - | SynExpr.Const(SynConst.Byte _, _) - | SynExpr.Const(SynConst.UInt16 _, _) - | SynExpr.Const(SynConst.UInt32 _, _) - | SynExpr.Const(SynConst.UInt64 _, _) - | SynExpr.Const(SynConst.UIntPtr _, _) - | SynExpr.Const(SynConst.SByte _, _) - | SynExpr.Const(SynConst.Int16 _, _) - | SynExpr.Const(SynConst.Int32 _, TextContainsLetter) - | SynExpr.Const(SynConst.Int64 _, _) - | SynExpr.Const(SynConst.IntPtr _, _) - | SynExpr.Const(SynConst.Decimal _, _) - | SynExpr.Const(SynConst.Double _, (TextEndsWithNumber | TextContainsLetter)) - | SynExpr.Const(SynConst.Single _, _) - | SynExpr.Const(SynConst.Measure _, _) - | SynExpr.Const(SynConst.UserNum _, _) -> Some DotSafeNumericLiteral - | _ -> None - - match expr, path with - // Check for nested matches, e.g., - // - // match … with … -> (…, match … with … -> … | … -> …) | … -> … - | SynExpr.Paren _, SyntaxNode.SynMatchClause _ :: path -> unnecessaryParentheses expr path - - // We always need parens for trait calls, e.g., - // - // let inline f x = (^a : (static member Parse : string -> ^a) x) - | SynExpr.Paren(expr = SynExpr.TraitCall _), _ -> ValueNone - - // Don't touch library-only stuff: - // - // (# "ldlen.multi 2 0" array : int #) - | SynExpr.Paren(expr = SynExpr.LibraryOnlyILAssembly _), _ - | SynExpr.Paren(expr = SynExpr.LibraryOnlyStaticOptimization _), _ - | SynExpr.Paren(expr = SynExpr.LibraryOnlyUnionCaseFieldGet _), _ - | SynExpr.Paren(expr = SynExpr.LibraryOnlyUnionCaseFieldSet _), _ -> ValueNone - - // Parens are required around the body expresion of a binding - // if the parenthesized expression would be invalid without its parentheses, e.g., - // - // let x = (x - // + y) - | SynExpr.Paren(rightParenRange = Some _; range = parenRange), - SyntaxNode.SynBinding(SynBinding(trivia = { LeadingKeyword = leadingKeyword })) :: _ when - containsSensitiveIndentation leadingKeyword.Range.StartColumn parenRange - -> - ValueNone - - // Parens are otherwise never required for binding bodies or for top-level expressions, e.g., - // - // let x = (…) - // _.member X = (…) - // (printfn "Hello, world.") - | SynExpr.Paren(rightParenRange = Some _; range = range), SyntaxNode.SynBinding _ :: _ - | SynExpr.Paren(rightParenRange = Some _; range = range), SyntaxNode.SynModule _ :: _ -> ValueSome range - - // Parens must be kept when there is a high-precedence function application - // before a prefix operator application before another expression that starts with a symbol, e.g., - // - // id -(-x) - // id -(-1y) - // id -($"") - // id -(@"") - // id -(<@ ValueNone @>) - // let (~+) _ = true in assert +($"{true}") - | SynExpr.Paren(expr = PrefixApp _ | StartsWithSymbol), - SyntaxNode.SynExpr(SynExpr.App _) :: SyntaxNode.SynExpr(HighPrecedenceApp | SynExpr.Assert _ | SynExpr.InferredUpcast _ | SynExpr.InferredDowncast _) :: _ -> - ValueNone - - // Parens are never required around suffixed or infixed numeric literals, e.g., - // - // (1l).ToString() - // (1uy).ToString() - // (0b1).ToString() - // (1e10).ToString() - // (1.0).ToString() - | SynExpr.Paren(expr = DotSafeNumericLiteral; rightParenRange = Some _; range = range), _ -> ValueSome range - - // Parens are required around bare decimal ints or doubles ending - // in dots when being dotted into, e.g., - // - // (1).ToString() - // (1.).ToString() - | SynExpr.Paren(expr = SynExpr.Const(constant = SynConst.Int32 _ | SynConst.Double _)), - SyntaxNode.SynExpr(SynExpr.DotGet _) :: _ -> ValueNone - - // Parens are required around join conditions: - // - // join … on (… = …) - | SynExpr.Paren(expr = SynExpr.App _), SyntaxNode.SynExpr(SynExpr.App _) :: SyntaxNode.SynExpr(SynExpr.JoinIn _) :: _ -> - ValueNone - - // Parens are not required around a few anointed expressions after inherit: - // - // inherit T(3) - // inherit T(null) - // inherit T("") - // … - | SynExpr.Paren(expr = AtomicExprAfterType; range = range), SyntaxNode.SynMemberDefn(SynMemberDefn.ImplicitInherit _) :: _ -> - ValueSome range - - // Parens are otherwise required in inherit T(x), etc. - | SynExpr.Paren _, SyntaxNode.SynMemberDefn(SynMemberDefn.ImplicitInherit _) :: _ -> ValueNone - - // We can't remove parens when they're required for fluent calls: - // - // x.M(y).N z - // x.M(y).[z] - // (f x)[z] - // (f(x))[z] - // x.M(y)[z] - | SynExpr.Paren _, SyntaxNode.SynExpr(SynExpr.App _) :: SyntaxNode.SynExpr(SynExpr.DotGet _ | SynExpr.DotIndexedGet _) :: _ - | SynExpr.Paren(expr = SynExpr.App _), - SyntaxNode.SynExpr(SynExpr.App(argExpr = SynExpr.ArrayOrListComputed(isArray = false))) :: _ - | SynExpr.Paren _, - SyntaxNode.SynExpr(SynExpr.App _) :: SyntaxNode.SynExpr(SynExpr.App(argExpr = SynExpr.ArrayOrListComputed(isArray = false))) :: _ -> - ValueNone - - // Parens must stay around binary equals expressions in argument - // position lest they be interpreted as named argument assignments: - // - // o.M((x = y)) - // o.N((x = y), z) - | SynExpr.Paren(expr = SynExpr.Paren(expr = InfixApp(Eq, _))), - SyntaxNode.SynExpr(SynExpr.App(funcExpr = SynExpr.LongIdent _)) :: _ - | SynExpr.Paren(expr = InfixApp(Eq, _)), - SyntaxNode.SynExpr(SynExpr.Paren _) :: SyntaxNode.SynExpr(SynExpr.App(funcExpr = SynExpr.LongIdent _)) :: _ - | SynExpr.Paren(expr = InfixApp(Eq, _)), - SyntaxNode.SynExpr(SynExpr.Tuple(isStruct = false)) :: SyntaxNode.SynExpr(SynExpr.Paren _) :: SyntaxNode.SynExpr(SynExpr.App( - funcExpr = SynExpr.LongIdent _)) :: _ -> ValueNone - - // The :: operator is parsed differently from other symbolic infix operators, - // so we need to give it special treatment. - - // Outer right: - // - // (x) :: xs - // (x * y) :: zs - // … - | SynExpr.Paren(rightParenRange = Some _), - SyntaxNode.SynExpr(SynExpr.Tuple(isStruct = false; exprs = [ SynExpr.Paren _; _ ])) :: (SyntaxNode.SynExpr(SynExpr.App( - isInfix = true)) :: _ as path) -> unnecessaryParentheses expr path - - // Outer left: - // - // x :: (xs) - // x :: (ys @ zs) - // … - | SynExpr.Paren(rightParenRange = Some _) as argExpr, - SyntaxNode.SynExpr(SynExpr.Tuple(isStruct = false; exprs = [ _; SynExpr.Paren _ ])) :: SyntaxNode.SynExpr(SynExpr.App( - isInfix = true) as outer) :: path -> - unnecessaryParentheses - expr - (SyntaxNode.SynExpr(SynExpr.App(ExprAtomicFlag.NonAtomic, false, outer, argExpr, outer.Range)) - :: path) - - // Ordinary nested expressions. - | SynExpr.Paren(expr = inner; leftParenRange = leftParenRange; rightParenRange = Some _ as rightParenRange; range = range), - SyntaxNode.SynExpr outer :: outerPath when not (containsSensitiveIndentation outer.Range.StartColumn range) -> - let dangling expr = - match expr with - | Dangling.Problematic subExpr -> - let parenzedSubExpr = SynExpr.Paren(subExpr, leftParenRange, rightParenRange, range) - - match outer with - | SynExpr.Tuple(exprs = exprs) -> not (obj.ReferenceEquals(subExpr, List.last exprs)) - | InfixApp(_, Left) -> true - | _ -> unnecessaryParentheses parenzedSubExpr outerPath |> ValueOption.isNone - - | _ -> false - - let problematic (exprRange: range) (delimiterRange: range) = - exprRange.EndLine = delimiterRange.EndLine - && exprRange.EndColumn < delimiterRange.StartColumn - - let anyProblematic matchOrTryRange clauses = - let rec loop = - function - | [] -> false - | SynMatchClause(trivia = trivia) :: clauses -> - trivia.BarRange |> Option.exists (problematic matchOrTryRange) - || trivia.ArrowRange |> Option.exists (problematic matchOrTryRange) - || loop clauses - - loop clauses - - match outer, inner with - | ConfusableWithTypeApp, _ -> ValueNone - - | SynExpr.IfThenElse _, Dangling.Sequential _ -> ValueNone - - | SynExpr.IfThenElse(trivia = trivia), Dangling.IfThen ifThenElse when - problematic ifThenElse.Range trivia.ThenKeyword - || trivia.ElseKeyword |> Option.exists (problematic ifThenElse.Range) - -> - ValueNone - - | SynExpr.TryFinally(trivia = trivia), Dangling.Try tryExpr when problematic tryExpr.Range trivia.FinallyKeyword -> - ValueNone - - | SynExpr.Match(clauses = clauses; trivia = { WithKeyword = withKeyword }), Dangling.Match matchOrTry when - problematic matchOrTry.Range withKeyword - || anyProblematic matchOrTry.Range clauses - -> - ValueNone - - | SynExpr.MatchBang(clauses = clauses; trivia = { WithKeyword = withKeyword }), Dangling.Match matchOrTry when - problematic matchOrTry.Range withKeyword - || anyProblematic matchOrTry.Range clauses - -> - ValueNone - - | SynExpr.MatchLambda(matchClauses = clauses), Dangling.Match matchOrTry when anyProblematic matchOrTry.Range clauses -> - ValueNone - - | SynExpr.TryWith(withCases = clauses; trivia = trivia), Dangling.Match matchOrTry when - problematic matchOrTry.Range trivia.WithKeyword - || anyProblematic matchOrTry.Range clauses - -> - ValueNone - - | SynExpr.Sequential(expr1 = SynExpr.Paren(expr = Is inner); expr2 = expr2), Dangling.Problematic _ when - problematic inner.Range expr2.Range - -> - ValueNone - - | SynExpr.Record(copyInfo = Some(SynExpr.Paren(expr = Is inner), _)), Dangling.Problematic _ - | SynExpr.AnonRecd(copyInfo = Some(SynExpr.Paren(expr = Is inner), _)), Dangling.Problematic _ -> ValueNone - - | SynExpr.Record(recordFields = recordFields), Dangling.Problematic _ -> - let rec loop recordFields = - match recordFields with - | [] -> ValueSome range - | SynExprRecordField(expr = Some(SynExpr.Paren(expr = Is inner)); blockSeparator = Some _) :: SynExprRecordField( - fieldName = SynLongIdent(id = id :: _), _) :: _ -> - if problematic inner.Range id.idRange then - ValueNone - else - ValueSome range - | _ :: recordFields -> loop recordFields - - loop recordFields - - | SynExpr.AnonRecd(recordFields = recordFields), Dangling.Problematic _ -> - let rec loop recordFields = - match recordFields with - | [] -> ValueSome range - | (_, Some _blockSeparator, SynExpr.Paren(expr = Is inner)) :: (SynLongIdent(id = id :: _), _, _) :: _ -> - if problematic inner.Range id.idRange then - ValueNone - else - ValueSome range - | _ :: recordFields -> loop recordFields - - loop recordFields - - | SynExpr.Paren _, SynExpr.Typed _ - | SynExpr.Quote _, SynExpr.Typed _ - | SynExpr.AnonRecd _, SynExpr.Typed _ - | SynExpr.Record _, SynExpr.Typed _ - | SynExpr.While(doExpr = SynExpr.Paren(expr = Is inner)), SynExpr.Typed _ - | SynExpr.WhileBang(doExpr = SynExpr.Paren(expr = Is inner)), SynExpr.Typed _ - | SynExpr.For(doBody = Is inner), SynExpr.Typed _ - | SynExpr.ForEach(bodyExpr = Is inner), SynExpr.Typed _ - | SynExpr.Match _, SynExpr.Typed _ - | SynExpr.Do _, SynExpr.Typed _ - | SynExpr.LetOrUse(body = Is inner), SynExpr.Typed _ - | SynExpr.TryWith _, SynExpr.Typed _ - | SynExpr.TryFinally _, SynExpr.Typed _ -> ValueSome range - | _, SynExpr.Typed _ -> ValueNone - - | OuterBinaryExpr inner (outerPrecedence, side), InnerBinaryExpr innerPrecedence -> - let ambiguous = - match Precedence.compare outerPrecedence innerPrecedence with - | 0 -> - match side, Assoc.ofPrecedence innerPrecedence with - | Non, _ - | _, Non - | Left, Right -> true - | Right, Right - | Left, Left -> false - | Right, Left -> - not (Precedence.sameKind outerPrecedence innerPrecedence) - || match innerPrecedence with - | Div - | Mod - | Sub -> true - | _ -> false - - | c -> c > 0 - - if ambiguous || dangling inner then - ValueNone - else - ValueSome range - - | OuterBinaryExpr inner (_, Right), (SynExpr.Sequential _ | SynExpr.LetOrUse(trivia = { InKeyword = None })) -> ValueNone - | OuterBinaryExpr inner (_, Right), inner -> if dangling inner then ValueNone else ValueSome range - - // new T(expr) - | SynExpr.New _, AtomicExprAfterType -> ValueSome range - | SynExpr.New _, _ -> ValueNone - - // { inherit T(expr); … } - | SynExpr.Record(baseInfo = Some(_, SynExpr.Paren(expr = Is inner), _, _, _)), AtomicExprAfterType -> ValueSome range - | SynExpr.Record(baseInfo = Some(_, SynExpr.Paren(expr = Is inner), _, _, _)), _ -> ValueNone - - | _, SynExpr.Paren _ - | _, SynExpr.Quote _ - | _, SynExpr.Const _ - | _, SynExpr.Tuple(isStruct = true) - | _, SynExpr.AnonRecd _ - | _, SynExpr.ArrayOrList _ - | _, SynExpr.Record _ - | _, SynExpr.ObjExpr _ - | _, SynExpr.ArrayOrListComputed _ - | _, SynExpr.ComputationExpr _ - | _, SynExpr.TypeApp _ - | _, SynExpr.Ident _ - | _, SynExpr.LongIdent _ - | _, SynExpr.DotGet _ - | _, SynExpr.DotLambda _ - | _, SynExpr.DotIndexedGet _ - | _, SynExpr.Null _ - | _, SynExpr.InterpolatedString _ - - | SynExpr.Paren _, _ - | SynExpr.Quote _, _ - | SynExpr.Typed _, _ - | SynExpr.AnonRecd _, _ - | SynExpr.Record _, _ - | SynExpr.ObjExpr _, _ - | SynExpr.While _, _ - | SynExpr.WhileBang _, _ - | SynExpr.For _, _ - | SynExpr.ForEach _, _ - | SynExpr.Lambda _, _ - | SynExpr.MatchLambda _, _ - | SynExpr.Match _, _ - | SynExpr.MatchBang _, _ - | SynExpr.LetOrUse _, _ - | SynExpr.LetOrUseBang _, _ - | SynExpr.Sequential _, _ - | SynExpr.Do _, _ - | SynExpr.DoBang _, _ - | SynExpr.IfThenElse _, _ - | SynExpr.TryWith _, _ - | SynExpr.TryFinally _, _ - | SynExpr.ComputationExpr _, _ - | SynExpr.InterpolatedString _, _ -> ValueSome range - - | _ -> ValueNone - - | _ -> ValueNone - - module SynPat = - let (|Last|) = List.last - - /// Matches if any pattern in the given list is a SynPat.Typed. - [] - let (|AnyTyped|_|) pats = - if - pats - |> List.exists (function - | SynPat.Typed _ -> true - | _ -> false) - then - ValueSome AnyTyped - else - ValueNone - - /// Matches if any member in the given list is an inherit - /// or implementation of an interface with generic type args. - [] - let (|AnyGenericInheritOrInterfaceImpl|_|) members = - if - members - |> List.exists (function - | SynMemberDefn.ImplicitInherit(inheritType = SynType.App(typeArgs = _ :: _)) - | SynMemberDefn.ImplicitInherit(inheritType = SynType.LongIdentApp(typeArgs = _ :: _)) - | SynMemberDefn.Interface(interfaceType = SynType.App(typeArgs = _ :: _)) - | SynMemberDefn.Interface(interfaceType = SynType.LongIdentApp(typeArgs = _ :: _)) -> true - | _ -> false) - then - ValueSome AnyGenericInheritOrInterfaceImpl - else - ValueNone - - /// Matches the rightmost potentially dangling nested pattern. - let rec (|Rightmost|) pat = - match pat with - | SynPat.Or(rhsPat = Rightmost pat) - | SynPat.ListCons(rhsPat = Rightmost pat) - | SynPat.As(rhsPat = Rightmost pat) - | SynPat.Ands(pats = Last(Rightmost pat)) - | SynPat.Tuple(isStruct = false; elementPats = Last(Rightmost pat)) -> pat - | pat -> pat - - /// Matches if the given pattern is atomic. - [] - let (|Atomic|_|) pat = - match pat with - | SynPat.Named _ - | SynPat.Wild _ - | SynPat.Paren _ - | SynPat.Tuple(isStruct = true) - | SynPat.Record _ - | SynPat.ArrayOrList _ - | SynPat.Const _ - | SynPat.LongIdent(argPats = SynArgPats.Pats []) - | SynPat.Null _ - | SynPat.QuoteExpr _ -> ValueSome Atomic - | _ -> ValueNone - - /// If the given pattern is a parenthesized pattern and the parentheses - /// are unnecessary in the given context, returns the unnecessary parentheses' range. - let unnecessaryParentheses pat path = - match pat, path with - // Parens are needed in: - // - // let (Pattern …) = … - // let (x: …, y…) = … - // let (x: …), (y: …) = … - // let! (x: …) = … - // and! (x: …) = … - // use! (x: …) = … - // _.member M(x: …) = … - // match … with (x: …) -> … - // match … with (x, y: …) -> … - // function (x: …) -> … - // fun (x, y, …) -> … - // fun (x: …) -> … - // fun (Pattern …) -> … - | SynPat.Paren(SynPat.Typed _, _), SyntaxNode.SynPat(Rightmost rightmost) :: SyntaxNode.SynMatchClause _ :: _ when - obj.ReferenceEquals(pat, rightmost) - -> - ValueNone - | SynPat.Paren(Rightmost(SynPat.Typed _), _), SyntaxNode.SynMatchClause _ :: _ - | SynPat.Paren(SynPat.Typed _, _), SyntaxNode.SynExpr(SynExpr.LetOrUseBang _) :: _ - | SynPat.Paren(SynPat.Typed _, _), - SyntaxNode.SynPat(SynPat.Tuple(isStruct = false)) :: SyntaxNode.SynExpr(SynExpr.LetOrUseBang _) :: _ - | SynPat.Paren(SynPat.Tuple(isStruct = false; elementPats = AnyTyped), _), SyntaxNode.SynExpr(SynExpr.LetOrUseBang _) :: _ - | SynPat.Paren(SynPat.Typed _, _), SyntaxNode.SynPat(SynPat.Tuple(isStruct = false)) :: SyntaxNode.SynBinding _ :: _ - | SynPat.Paren(SynPat.Tuple(isStruct = false; elementPats = AnyTyped), _), SyntaxNode.SynBinding _ :: _ - | SynPat.Paren(SynPat.LongIdent(argPats = SynArgPats.Pats(_ :: _)), _), SyntaxNode.SynBinding _ :: _ - | SynPat.Paren(SynPat.LongIdent(argPats = SynArgPats.Pats(_ :: _)), _), SyntaxNode.SynExpr(SynExpr.Lambda _) :: _ - | SynPat.Paren(SynPat.Tuple(isStruct = false), _), SyntaxNode.SynExpr(SynExpr.Lambda(parsedData = Some _)) :: _ - | SynPat.Paren(SynPat.Typed _, _), SyntaxNode.SynExpr(SynExpr.Lambda(parsedData = Some _)) :: _ -> ValueNone - - // () is parsed as this. - | SynPat.Paren(SynPat.Const(SynConst.Unit, _), _), _ -> ValueNone - - // (()) is required when overriding a generic member - // where unit is the generic type argument: - // - // type C<'T> = abstract M : 'T -> unit - // let _ = { new C with override _.M (()) = () } - | SynPat.Paren(SynPat.Paren(SynPat.Const(SynConst.Unit, _), _), _), - SyntaxNode.SynPat(SynPat.LongIdent _) :: SyntaxNode.SynBinding _ :: SyntaxNode.SynExpr(SynExpr.ObjExpr( - objType = SynType.App(typeArgs = _ :: _) | SynType.LongIdentApp(typeArgs = _ :: _))) :: _ - | SynPat.Paren(SynPat.Paren(SynPat.Const(SynConst.Unit, _), _), _), - SyntaxNode.SynPat(SynPat.LongIdent _) :: SyntaxNode.SynBinding _ :: SyntaxNode.SynMemberDefn _ :: SyntaxNode.SynTypeDefn(SynTypeDefn( - typeRepr = SynTypeDefnRepr.ObjectModel(members = AnyGenericInheritOrInterfaceImpl))) :: _ -> ValueNone - - // Parens are required around the atomic argument of - // any additional `new` constructor that is not the last. - // - // type T … = - // new (x) = … - // new (x, y) = … - | SynPat.Paren(Atomic, range), - SyntaxNode.SynPat(SynPat.LongIdent(longDotId = SynLongIdent(id = [ Ident "new" ]))) :: SyntaxNode.SynBinding _ :: SyntaxNode.SynMemberDefn _ :: SyntaxNode.SynTypeDefn(SynTypeDefn( - typeRepr = SynTypeDefnRepr.ObjectModel(members = members))) :: _ -> - let lastNew = - (ValueNone, members) - ||> List.fold (fun lastNew ``member`` -> - match ``member`` with - | SynMemberDefn.Member( - memberDefn = SynBinding(headPat = SynPat.LongIdent(longDotId = SynLongIdent(id = [ Ident "new" ])))) -> - ValueSome ``member`` - | _ -> lastNew) - - match lastNew with - | ValueSome(SynMemberDefn.Member(memberDefn = SynBinding(headPat = SynPat.LongIdent(argPats = SynArgPats.Pats [ Is pat ])))) -> - ValueSome range - | _ -> ValueNone - - // Parens are otherwise never needed in these cases: - // - // let (x: …) = … - // for (…) in (…) do … - // let! (…) = … - // and! (…) = … - // use! (…) = … - // match … with (…) -> … - // function (…) -> … - // function (Pattern …) -> … - // fun (x) -> … - | SynPat.Paren(_, range), SyntaxNode.SynBinding _ :: _ - | SynPat.Paren(_, range), SyntaxNode.SynExpr(SynExpr.ForEach _) :: _ - | SynPat.Paren(_, range), SyntaxNode.SynExpr(SynExpr.LetOrUseBang _) :: _ - | SynPat.Paren(_, range), SyntaxNode.SynMatchClause _ :: _ - | SynPat.Paren(Atomic, range), SyntaxNode.SynExpr(SynExpr.Lambda(parsedData = Some _)) :: _ -> ValueSome range - - // Nested patterns. - | SynPat.Paren(inner, range), SyntaxNode.SynPat outer :: _ -> - match outer, inner with - // (x :: xs) :: ys - // (x, xs) :: ys - | SynPat.ListCons(lhsPat = SynPat.Paren(pat = Is inner)), SynPat.ListCons _ - | SynPat.ListCons(lhsPat = SynPat.Paren(pat = Is inner)), SynPat.Tuple(isStruct = false) -> ValueNone - - // A as (B | C) - // A as (B & C) - // x as (y, z) - // xs as (y :: zs) - | SynPat.As(rhsPat = SynPat.Paren(pat = Is inner)), - (SynPat.Or _ | SynPat.Ands _ | SynPat.Tuple(isStruct = false) | SynPat.ListCons _) -> ValueNone - - // (A | B) :: xs - // (A & B) :: xs - // (x as y) :: xs - | SynPat.ListCons _, SynPat.Or _ - | SynPat.ListCons _, SynPat.Ands _ - | SynPat.ListCons _, SynPat.As _ -> ValueNone - - // Pattern (x = (…)) - | SynPat.LongIdent(argPats = SynArgPats.NamePatPairs _), _ -> ValueSome range - - // Pattern (x : int) - // Pattern ([] x) - // Pattern (:? int) - // Pattern (A :: _) - // Pattern (A | B) - // Pattern (A & B) - // Pattern (A as B) - // Pattern (A, B) - // Pattern1 (Pattern2 (x = A)) - // Pattern1 (Pattern2 x y) - | SynPat.LongIdent _, SynPat.Typed _ - | SynPat.LongIdent _, SynPat.Attrib _ - | SynPat.LongIdent _, SynPat.IsInst _ - | SynPat.LongIdent _, SynPat.ListCons _ - | SynPat.LongIdent _, SynPat.Or _ - | SynPat.LongIdent _, SynPat.Ands _ - | SynPat.LongIdent _, SynPat.As _ - | SynPat.LongIdent _, SynPat.Tuple(isStruct = false) - | SynPat.LongIdent _, SynPat.LongIdent(argPats = SynArgPats.NamePatPairs _) - | SynPat.LongIdent _, SynPat.LongIdent(argPats = SynArgPats.Pats(_ :: _)) - - // A | (B as C) - // A & (B as C) - // A, (B as C) - | SynPat.Or _, SynPat.As _ - | SynPat.Ands _, SynPat.As _ - | SynPat.Tuple _, SynPat.As _ - - // x, (y, z) - // x & (y, z) - // (x, y) & z - | SynPat.Tuple _, SynPat.Tuple(isStruct = false) - | SynPat.Ands _, SynPat.Tuple(isStruct = false) - - // A, (B | C) - // A & (B | C) - | SynPat.Tuple _, SynPat.Or _ - | SynPat.Ands _, SynPat.Or _ -> ValueNone - - // (x : int) & y - // x & (y : int) & z - | SynPat.Ands(Last(SynPat.Paren(pat = Is inner)), _), SynPat.Typed _ -> ValueSome range - | SynPat.Ands _, SynPat.Typed _ -> ValueNone - - | _, SynPat.Const _ - | _, SynPat.Wild _ - | _, SynPat.Named _ - | _, SynPat.Typed _ - | _, SynPat.LongIdent(argPats = SynArgPats.Pats []) - | _, SynPat.Tuple(isStruct = true) - | _, SynPat.Paren _ - | _, SynPat.ArrayOrList _ - | _, SynPat.Record _ - | _, SynPat.Null _ - | _, SynPat.OptionalVal _ - | _, SynPat.IsInst _ - | _, SynPat.QuoteExpr _ - - | SynPat.Or _, _ - | SynPat.ListCons _, _ - | SynPat.Ands _, _ - | SynPat.As _, _ - | SynPat.LongIdent _, _ - | SynPat.Tuple _, _ - | SynPat.Paren _, _ - | SynPat.ArrayOrList _, _ - | SynPat.Record _, _ -> ValueSome range - - | _ -> ValueNone - - | _ -> ValueNone - - let getUnnecessaryParentheses (getSourceLineStr: int -> string) (parsedInput: ParsedInput) : Async = - async { - let ranges = HashSet Range.comparer - - let visitor = - { new SyntaxVisitorBase() with - member _.VisitExpr(path, _, defaultTraverse, expr) = - SynExpr.unnecessaryParentheses getSourceLineStr expr path - |> ValueOption.iter (ranges.Add >> ignore) - - defaultTraverse expr - - member _.VisitPat(path, defaultTraverse, pat) = - SynPat.unnecessaryParentheses pat path - |> ValueOption.iter (ranges.Add >> ignore) - - defaultTraverse pat - } - - SyntaxTraversal.traverseAll visitor parsedInput - return ranges - } diff --git a/src/Compiler/Service/ServiceAnalysis.fsi b/src/Compiler/Service/ServiceAnalysis.fsi index 836bfce0c56..672cf088759 100644 --- a/src/Compiler/Service/ServiceAnalysis.fsi +++ b/src/Compiler/Service/ServiceAnalysis.fsi @@ -3,7 +3,6 @@ namespace FSharp.Compiler.EditorServices open FSharp.Compiler.CodeAnalysis -open FSharp.Compiler.Syntax open FSharp.Compiler.Text module public UnusedOpens = @@ -32,14 +31,3 @@ module public UnusedDeclarations = /// Get all unused declarations in a file val getUnusedDeclarations: checkFileResults: FSharpCheckFileResults * isScriptFile: bool -> Async> - -module public UnnecessaryParentheses = - - /// Gets the ranges of all unnecessary pairs of parentheses in a file. - /// - /// Note that this may include pairs of nested ranges each of whose - /// lack of necessity depends on the other's presence, such - /// that it is valid to remove either set of parentheses but not both, e.g.: - /// - /// (x.M(y)).N → (x.M y).N ↮ x.M(y).N - val getUnnecessaryParentheses: getSourceLineStr: (int -> string) -> parsedInput: ParsedInput -> Async diff --git a/src/Compiler/Service/ServiceDeclarationLists.fs b/src/Compiler/Service/ServiceDeclarationLists.fs index 5488baa107a..d8499132fdc 100644 --- a/src/Compiler/Service/ServiceDeclarationLists.fs +++ b/src/Compiler/Service/ServiceDeclarationLists.fs @@ -358,19 +358,7 @@ module DeclarationListHelpers = | Item.CtorGroup(_, minfos) | Item.MethodGroup(_, minfos, _) -> FormatOverloadsToList infoReader m denv item minfos symbol width - - // The 'fake' zero-argument constructors of .NET interfaces. - // This ideally should never appear in intellisense, but we do get here in repros like: - // type IFoo = abstract F : int - // type II = IFoo // remove 'type II = ' and quickly hover over IFoo before it gets squiggled for 'invalid use of interface type' - // and in that case we'll just show the interface type name. - | Item.FakeInterfaceCtor ty -> - let ty, _ = PrettyTypes.PrettifyType g ty - let layout = NicePrint.layoutTyconRef denv (tcrefOfAppTy g ty) - let layout = PrintUtilities.squashToWidth width layout - let layout = toArray layout - ToolTipElement.Single(layout, xml, ?symbol = symbol) - + // The 'fake' representation of constructors of .NET delegate types | Item.DelegateCtor delTy -> let delTy, _cxs = PrettyTypes.PrettifyType g delTy @@ -848,10 +836,6 @@ module internal DescriptionListsImpl = let _prettyTyparInst, prettyRetTyL = NicePrint.prettyLayoutOfUncurriedSig denv item.TyparInstantiation [] retTy [], prettyRetTyL // no parameter data available for binary operators like 'zip', 'join' and 'groupJoin' since they use bespoke syntax - | Item.FakeInterfaceCtor ty -> - let _prettyTyparInst, prettyRetTyL = NicePrint.prettyLayoutOfUncurriedSig denv item.TyparInstantiation [] ty - [], prettyRetTyL - | Item.DelegateCtor delTy -> let (SigOfFunctionForDelegate(_, _, _, delFuncTy)) = GetSigOfFunctionForDelegate infoReader delTy m AccessibleFromSomewhere @@ -940,7 +924,6 @@ module internal DescriptionListsImpl = | Item.Property _ -> FSharpGlyph.Property | Item.CtorGroup _ | Item.DelegateCtor _ - | Item.FakeInterfaceCtor _ | Item.CustomOperation _ -> FSharpGlyph.Method | Item.MethodGroup (_, minfos, _) when minfos |> List.forall (fun minfo -> minfo.IsExtensionMember) -> FSharpGlyph.ExtensionMethod | Item.MethodGroup _ -> FSharpGlyph.Method @@ -986,7 +969,6 @@ module internal DescriptionListsImpl = | Item.CtorGroup(nm, cinfos) -> List.map (fun minfo -> Item.CtorGroup(nm, [minfo])) cinfos | Item.Trait traitInfo -> if traitInfo.GetLogicalArgumentTypes(g).IsEmpty then [] else [item] - | Item.FakeInterfaceCtor _ | Item.DelegateCtor _ -> [item] | Item.NewDef _ | Item.ILField _ -> [] @@ -1107,9 +1089,9 @@ type DeclarationListInfo(declarations: DeclarationListItem[], isForType: bool, i items |> List.map (fun x -> match x.Item with + | Item.Types (_, TType_app(tcref, _, _) :: _) when isInterfaceTyconRef tcref -> { x with MinorPriority = 1000 + tcref.TyparsNoRange.Length } | Item.Types (_, TType_app(tcref, _, _) :: _) -> { x with MinorPriority = 1 + tcref.TyparsNoRange.Length } // Put delegate ctors after types, sorted by #typars. RemoveDuplicateItems will remove FakeInterfaceCtor and DelegateCtor if an earlier type is also reported with this name - | Item.FakeInterfaceCtor (TType_app(tcref, _, _)) | Item.DelegateCtor (TType_app(tcref, _, _)) -> { x with MinorPriority = 1000 + tcref.TyparsNoRange.Length } // Put type ctors after types, sorted by #typars. RemoveDuplicateItems will remove DefaultStructCtors if a type is also reported with this name | Item.CtorGroup (_, cinfo :: _) -> { x with MinorPriority = 1000 + 10 * cinfo.DeclaringTyconRef.TyparsNoRange.Length } diff --git a/src/Compiler/Service/ServiceNavigation.fs b/src/Compiler/Service/ServiceNavigation.fs index 7f912e07e09..03afe63b373 100755 --- a/src/Compiler/Service/ServiceNavigation.fs +++ b/src/Compiler/Service/ServiceNavigation.fs @@ -377,7 +377,14 @@ module NavigationImpl = | SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = lid; accessibility = access); decls = decls; range = m) -> // Find let bindings (for the right dropdown) let nested = processNestedDeclarations (decls) - let newBaseName = (if (baseName = "") then "" else baseName + ".") + (textOfLid lid) + + let newBaseName = + (if (String.IsNullOrEmpty(baseName)) then + "" + else + baseName + ".") + + (textOfLid lid) + let other = processNavigationTopLevelDeclarations (newBaseName, decls) let mBody = unionRangesChecked (rangeOfDecls nested) (moduleRange (rangeOfLid lid) other) @@ -587,7 +594,14 @@ module NavigationImpl = | SynModuleSigDecl.NestedModule(moduleInfo = SynComponentInfo(longId = lid; accessibility = access); moduleDecls = decls; range = m) -> // Find let bindings (for the right dropdown) let nested = processNestedSigDeclarations (decls) - let newBaseName = (if baseName = "" then "" else baseName + ".") + (textOfLid lid) + + let newBaseName = + (if String.IsNullOrEmpty(baseName) then + "" + else + baseName + ".") + + (textOfLid lid) + let other = processNavigationTopLevelSigDeclarations (newBaseName, decls) // Get nested modules and types (for the left dropdown) diff --git a/src/Compiler/Service/ServiceParseTreeWalk.fs b/src/Compiler/Service/ServiceParseTreeWalk.fs index e18c3cff03f..e358b2bf921 100644 --- a/src/Compiler/Service/ServiceParseTreeWalk.fs +++ b/src/Compiler/Service/ServiceParseTreeWalk.fs @@ -13,7 +13,6 @@ open FSharp.Compiler.Text open FSharp.Compiler.Text.Position open FSharp.Compiler.Text.Range -/// used to track route during traversal AST [] type SyntaxNode = | SynPat of SynPat @@ -31,6 +30,23 @@ type SyntaxNode = | SynTypeDefnSig of SynTypeDefnSig | SynMemberSig of SynMemberSig + member this.Range = + match this with + | SynPat pat -> pat.Range + | SynType ty -> ty.Range + | SynExpr expr -> expr.Range + | SynModule modul -> modul.Range + | SynModuleOrNamespace moduleOrNamespace -> moduleOrNamespace.Range + | SynTypeDefn tyDef -> tyDef.Range + | SynMemberDefn memberDef -> memberDef.Range + | SynMatchClause matchClause -> matchClause.Range + | SynBinding binding -> binding.RangeOfBindingWithRhs + | SynModuleOrNamespaceSig moduleOrNamespaceSig -> moduleOrNamespaceSig.Range + | SynModuleSigDecl moduleSigDecl -> moduleSigDecl.Range + | SynValSig(SynValSig.SynValSig(range = range)) -> range + | SynTypeDefnSig tyDefSig -> tyDefSig.Range + | SynMemberSig memberSig -> memberSig.Range + type SyntaxVisitorPath = SyntaxNode list [] @@ -163,10 +179,10 @@ type SyntaxVisitorBase<'T>() = None /// VisitSimplePats allows overriding behavior when visiting simple pats - abstract VisitSimplePats: path: SyntaxVisitorPath * synPats: SynSimplePat list -> 'T option + abstract VisitSimplePats: path: SyntaxVisitorPath * pat: SynPat -> 'T option - default _.VisitSimplePats(path, synPats) = - ignore (path, synPats) + default _.VisitSimplePats(path, pat) = + ignore (path, pat) None /// VisitPat allows overriding behavior when visiting patterns @@ -211,6 +227,15 @@ type SyntaxVisitorBase<'T>() = ignore path defaultTraverse valSig +[] +module private ParsedInputExtensions = + type ParsedInput with + + member parsedInput.Contents = + match parsedInput with + | ParsedInput.ImplFile file -> file.Contents |> List.map SyntaxNode.SynModuleOrNamespace + | ParsedInput.SigFile file -> file.Contents |> List.map SyntaxNode.SynModuleOrNamespaceSig + /// A range of utility functions to assist with traversing an AST module SyntaxTraversal = // treat ranges as though they are half-open: [,) @@ -304,7 +329,7 @@ module SyntaxTraversal = (pick: pos -> range -> obj -> (range * (unit -> 'T option)) list -> 'T option) (pos: pos) (visitor: SyntaxVisitorBase<'T>) - (parseTree: ParsedInput) + (ast: SyntaxNode list) : 'T option = let pick x = pick pos x @@ -749,15 +774,18 @@ module SyntaxTraversal = visitor.VisitPat(origPath, defaultTraverse, pat) - and traverseSynSimplePats origPath (pats: SynSimplePat list) = - match visitor.VisitSimplePats(origPath, pats) with + and traverseSynSimplePats origPath (pat: SynPat) = + match visitor.VisitSimplePats(origPath, pat) with | None -> - pats - |> List.tryPick (fun pat -> + let rec loop (pat: SynPat) = match pat with - | SynSimplePat.Attrib(attributes = attributes; range = m) -> - attributeApplicationDives origPath attributes |> pick m attributes - | _ -> None) + | SynPat.Paren(pat = pat) + | SynPat.Typed(pat = pat) -> loop pat + | SynPat.Tuple(elementPats = pats) -> List.tryPick loop pats + | SynPat.Attrib(_, attributes, m) -> attributeApplicationDives origPath attributes |> pick m attributes + | _ -> None + + loop pat | x -> x and traverseSynType origPath (StripParenTypes ty) = @@ -888,9 +916,8 @@ module SyntaxTraversal = traverseSynBinding path getBinding |> Option.orElseWith (fun () -> traverseSynBinding path setBinding) - | SynMemberDefn.ImplicitCtor(ctorArgs = simplePats) -> - match simplePats with - | SynSimplePats.SimplePats(pats = simplePats) -> traverseSynSimplePats path simplePats + | SynMemberDefn.ImplicitCtor(ctorArgs = pat) -> traverseSynSimplePats path pat + | SynMemberDefn.ImplicitInherit(synType, synExpr, _identOption, range) -> [ dive () synType.Range (fun () -> @@ -1062,40 +1089,377 @@ module SyntaxTraversal = attributeApplicationDives path attributes |> pick m.Range attributes | SynMemberSig.NestedType(nestedType = nestedType) -> traverseSynTypeDefnSig path nestedType - match parseTree with - | ParsedInput.ImplFile file -> - let l = file.Contents + let fileRange = + (range0, ast) ||> List.fold (fun acc node -> unionRanges acc node.Range) + + ast + |> List.map (fun node -> + match node with + | SyntaxNode.SynModuleOrNamespace moduleOrNamespace -> + dive moduleOrNamespace moduleOrNamespace.Range (traverseSynModuleOrNamespace []) + | SyntaxNode.SynModuleOrNamespaceSig moduleOrNamespaceSig -> + dive moduleOrNamespaceSig moduleOrNamespaceSig.Range (traverseSynModuleOrNamespaceSig []) + | SyntaxNode.SynPat pat -> dive pat pat.Range (traversePat []) + | SyntaxNode.SynType ty -> dive ty ty.Range (traverseSynType []) + | SyntaxNode.SynExpr expr -> dive expr expr.Range (traverseSynExpr []) + | SyntaxNode.SynModule modul -> dive modul modul.Range (traverseSynModuleDecl []) + | SyntaxNode.SynTypeDefn tyDef -> dive tyDef tyDef.Range (traverseSynTypeDefn []) + | SyntaxNode.SynMemberDefn memberDef -> dive memberDef memberDef.Range (traverseSynMemberDefn [] (fun _ -> None)) + | SyntaxNode.SynMatchClause matchClause -> dive matchClause matchClause.Range (traverseSynMatchClause []) + | SyntaxNode.SynBinding binding -> dive binding binding.RangeOfBindingWithRhs (traverseSynBinding []) + | SyntaxNode.SynModuleSigDecl moduleSigDecl -> dive moduleSigDecl moduleSigDecl.Range (traverseSynModuleSigDecl []) + | SyntaxNode.SynValSig(SynValSig.SynValSig(range = range) as valSig) -> dive valSig range (traverseSynValSig []) + | SyntaxNode.SynTypeDefnSig tyDefSig -> dive tyDefSig tyDefSig.Range (traverseSynTypeDefnSig []) + | SyntaxNode.SynMemberSig memberSig -> dive memberSig memberSig.Range (traverseSynMemberSig [])) + |> pick fileRange ast - let fileRange = -#if DEBUG - match l with - | [] -> range0 - | _ -> l |> List.map (fun x -> x.Range) |> List.reduce unionRanges -#else - range0 // only used for asserting, does not matter in non-debug -#endif - l - |> List.map (fun x -> dive x x.Range (traverseSynModuleOrNamespace [])) - |> pick fileRange l - | ParsedInput.SigFile sigFile -> - let l = sigFile.Contents + /// traverse an implementation file walking all the way down to SynExpr or TypeAbbrev at a particular location + /// + let Traverse (pos: pos, parseTree: ParsedInput, visitor: SyntaxVisitorBase<'T>) = + traverseUntil pick pos visitor parseTree.Contents - let fileRange = -#if DEBUG - match l with - | [] -> range0 - | _ -> l |> List.map (fun x -> x.Range) |> List.reduce unionRanges -#else - range0 // only used for asserting, does not matter in non-debug -#endif - l - |> List.map (fun x -> dive x x.Range (traverseSynModuleOrNamespaceSig [])) - |> pick fileRange l - - let traverseAll (visitor: SyntaxVisitorBase<'T>) (parseTree: ParsedInput) : unit = - let pick _ _ _ diveResults = - let rec loop = - function +[] +[] +module SyntaxNode = + let (|Attributes|) node = + let (|All|) = List.collect + let field (SynField(attributes = attributes)) = attributes + let unionCase (SynUnionCase(attributes = attributes)) = attributes + let enumCase (SynEnumCase(attributes = attributes)) = attributes + let typar (SynTyparDecl(attributes = attributes)) = attributes + + let (|SynComponentInfo|) componentInfo = + match componentInfo with + | SynComponentInfo(attributes = attributes; typeParams = Some(SynTyparDecls.PrefixList(decls = All typar attributes'))) + | SynComponentInfo(attributes = attributes; typeParams = Some(SynTyparDecls.PostfixList(decls = All typar attributes'))) + | SynComponentInfo( + attributes = attributes; typeParams = Some(SynTyparDecls.SinglePrefix(decl = SynTyparDecl(attributes = attributes')))) -> + attributes @ attributes' + | SynComponentInfo(attributes = attributes) -> attributes + + let (|SynBinding|) binding = + match binding with + | SynBinding(attributes = attributes; returnInfo = Some(SynBindingReturnInfo(attributes = attributes'))) -> + attributes @ attributes' + | SynBinding(attributes = attributes) -> attributes + + match node with + | SyntaxNode.SynModuleOrNamespace(SynModuleOrNamespace(attribs = attributes)) + | SyntaxNode.SynModuleOrNamespaceSig(SynModuleOrNamespaceSig(attribs = attributes)) + | SyntaxNode.SynModule(SynModuleDecl.Attributes(attributes = attributes)) + | SyntaxNode.SynTypeDefn(SynTypeDefn(typeInfo = SynComponentInfo attributes)) + | SyntaxNode.SynTypeDefn(SynTypeDefn( + typeRepr = SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.Record(recordFields = All field attributes), _))) + | SyntaxNode.SynTypeDefn(SynTypeDefn( + typeRepr = SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.Union(unionCases = All unionCase attributes), _))) + | SyntaxNode.SynTypeDefn(SynTypeDefn( + typeRepr = SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.Enum(cases = All enumCase attributes), _))) + | SyntaxNode.SynMemberDefn(SynMemberDefn.AutoProperty(attributes = attributes)) + | SyntaxNode.SynMemberDefn(SynMemberDefn.AbstractSlot(slotSig = SynValSig(attributes = attributes))) + | SyntaxNode.SynMemberDefn(SynMemberDefn.ImplicitCtor(attributes = attributes)) + | SyntaxNode.SynBinding(SynBinding attributes) + | SyntaxNode.SynPat(SynPat.Attrib(attributes = attributes)) + | SyntaxNode.SynType(SynType.SignatureParameter(attributes = attributes)) + | SyntaxNode.SynValSig(SynValSig(attributes = attributes)) -> attributes + | _ -> [] + +[] +[] +module ParsedInput = + let fold folder state (parsedInput: ParsedInput) = + let mutable state = state + + let visitor = + { new SyntaxVisitorBase() with + member _.VisitExpr(path, _, defaultTraverse, expr) = + match path with + | SyntaxNode.SynMemberDefn _ as parent :: path -> state <- folder state path parent + | _ -> () + + state <- folder state path (SyntaxNode.SynExpr expr) + defaultTraverse expr + + member _.VisitPat(path, defaultTraverse, pat) = + state <- folder state path (SyntaxNode.SynPat pat) + defaultTraverse pat + + member _.VisitType(path, defaultTraverse, synType) = + match path with + | SyntaxNode.SynMemberDefn _ | SyntaxNode.SynMemberSig _ as parent :: path -> state <- folder state path parent + | _ -> () + + state <- folder state path (SyntaxNode.SynType synType) + defaultTraverse synType + + member _.VisitModuleDecl(path, defaultTraverse, synModuleDecl) = + state <- folder state path (SyntaxNode.SynModule synModuleDecl) + + match synModuleDecl with + | SynModuleDecl.Types(types, _) -> + let path = SyntaxNode.SynModule synModuleDecl :: path + + for ty in types do + state <- folder state path (SyntaxNode.SynTypeDefn ty) + + | _ -> () + + defaultTraverse synModuleDecl + + member _.VisitModuleOrNamespace(path, synModuleOrNamespace) = + state <- folder state path (SyntaxNode.SynModuleOrNamespace synModuleOrNamespace) + None + + member _.VisitMatchClause(path, defaultTraverse, matchClause) = + state <- folder state path (SyntaxNode.SynMatchClause matchClause) + defaultTraverse matchClause + + member _.VisitBinding(path, defaultTraverse, synBinding) = + match path with + | SyntaxNode.SynMemberDefn _ as parent :: path -> state <- folder state path parent + | _ -> () + + state <- folder state path (SyntaxNode.SynBinding synBinding) + defaultTraverse synBinding + + member _.VisitModuleOrNamespaceSig(path, synModuleOrNamespaceSig) = + state <- folder state path (SyntaxNode.SynModuleOrNamespaceSig synModuleOrNamespaceSig) + None + + member _.VisitModuleSigDecl(path, defaultTraverse, synModuleSigDecl) = + state <- folder state path (SyntaxNode.SynModuleSigDecl synModuleSigDecl) + + match synModuleSigDecl with + | SynModuleSigDecl.Types(types, _) -> + let path = SyntaxNode.SynModuleSigDecl synModuleSigDecl :: path + + for ty in types do + state <- folder state path (SyntaxNode.SynTypeDefnSig ty) + + | _ -> () + + defaultTraverse synModuleSigDecl + + member _.VisitValSig(path, defaultTraverse, valSig) = + match path with + | SyntaxNode.SynMemberSig _ as parent :: path -> state <- folder state path parent + | _ -> () + + state <- folder state path (SyntaxNode.SynValSig valSig) + defaultTraverse valSig + + member _.VisitSimplePats(path, _pat) = + match path with + | SyntaxNode.SynMemberDefn _ as node :: path -> state <- folder state path node + | _ -> () + + None + + member _.VisitInterfaceSynMemberDefnType(path, _synType) = + match path with + | SyntaxNode.SynMemberDefn _ as node :: path -> state <- folder state path node + | _ -> () + + None + } + + let pickAll _ _ _ diveResults = + let rec loop diveResults = + match diveResults with + | [] -> None + | (_, project) :: rest -> + ignore (project ()) + loop rest + + loop diveResults + + let ast = parsedInput.Contents + let m = (range0, ast) ||> List.fold (fun acc node -> unionRanges acc node.Range) + ignore (SyntaxTraversal.traverseUntil pickAll m.End visitor ast) + state + + let private foldWhileImpl pick pos folder state (ast: SyntaxNode list) = + let mutable state = state + + let visitor = + { new SyntaxVisitorBase() with + member _.VisitExpr(path, _, defaultTraverse, expr) = + match path with + | SyntaxNode.SynMemberDefn _ as parent :: path -> + match folder state path parent with + | Some state' -> + match folder state' path (SyntaxNode.SynExpr expr) with + | Some state' -> + state <- state' + defaultTraverse expr + | None -> Some() + | None -> Some() + | _ -> + match folder state path (SyntaxNode.SynExpr expr) with + | Some state' -> + state <- state' + defaultTraverse expr + | None -> Some() + + member _.VisitPat(path, defaultTraverse, pat) = + match folder state path (SyntaxNode.SynPat pat) with + | Some state' -> + state <- state' + defaultTraverse pat + | None -> Some() + + member _.VisitType(path, defaultTraverse, synType) = + match path with + | SyntaxNode.SynMemberDefn _ | SyntaxNode.SynMemberSig _ as parent :: path -> + match folder state path parent with + | Some state' -> + match folder state' path (SyntaxNode.SynType synType) with + | Some state' -> + state <- state' + defaultTraverse synType + | None -> Some() + | None -> Some() + | _ -> + match folder state path (SyntaxNode.SynType synType) with + | Some state' -> + state <- state' + defaultTraverse synType + | None -> Some() + + member _.VisitModuleDecl(path, defaultTraverse, synModuleDecl) = + match folder state path (SyntaxNode.SynModule synModuleDecl) with + | Some state' -> + state <- state' + + match synModuleDecl with + | SynModuleDecl.Types(types, _) -> + let path = SyntaxNode.SynModule synModuleDecl :: path + + let rec loop types = + match types with + | [] -> defaultTraverse synModuleDecl + | ty :: types -> + match folder state path (SyntaxNode.SynTypeDefn ty) with + | Some state' -> + state <- state' + loop types + | None -> Some() + + loop types + + | _ -> defaultTraverse synModuleDecl + + | None -> Some() + + member _.VisitModuleOrNamespace(path, synModuleOrNamespace) = + match folder state path (SyntaxNode.SynModuleOrNamespace synModuleOrNamespace) with + | Some state' -> + state <- state' + None + | None -> Some() + + member _.VisitMatchClause(path, defaultTraverse, matchClause) = + match folder state path (SyntaxNode.SynMatchClause matchClause) with + | Some state' -> + state <- state' + defaultTraverse matchClause + | None -> Some() + + member _.VisitBinding(path, defaultTraverse, synBinding) = + match path with + | SyntaxNode.SynMemberDefn _ as parent :: path -> + match folder state path parent with + | Some state' -> + match folder state' path (SyntaxNode.SynBinding synBinding) with + | Some state' -> + state <- state' + defaultTraverse synBinding + | None -> Some() + | None -> Some() + | _ -> + match folder state path (SyntaxNode.SynBinding synBinding) with + | Some state' -> + state <- state' + defaultTraverse synBinding + | None -> Some() + + member _.VisitModuleOrNamespaceSig(path, synModuleOrNamespaceSig) = + match folder state path (SyntaxNode.SynModuleOrNamespaceSig synModuleOrNamespaceSig) with + | Some state' -> + state <- state' + None + | None -> Some() + + member _.VisitModuleSigDecl(path, defaultTraverse, synModuleSigDecl) = + match folder state path (SyntaxNode.SynModuleSigDecl synModuleSigDecl) with + | Some state' -> + state <- state' + + match synModuleSigDecl with + | SynModuleSigDecl.Types(types, _) -> + let path = SyntaxNode.SynModuleSigDecl synModuleSigDecl :: path + + let rec loop types = + match types with + | [] -> defaultTraverse synModuleSigDecl + | ty :: types -> + match folder state path (SyntaxNode.SynTypeDefnSig ty) with + | Some state' -> + state <- state' + loop types + | None -> Some() + + loop types + + | _ -> defaultTraverse synModuleSigDecl + + | None -> Some() + + member _.VisitValSig(path, defaultTraverse, valSig) = + match path with + | SyntaxNode.SynMemberSig _ as parent :: path -> + match folder state path parent with + | Some state' -> + match folder state' path (SyntaxNode.SynValSig valSig) with + | Some state' -> + state <- state' + defaultTraverse valSig + | None -> Some() + | None -> Some() + | _ -> + match folder state path (SyntaxNode.SynValSig valSig) with + | Some state' -> + state <- state' + defaultTraverse valSig + | None -> Some() + + member _.VisitSimplePats(path, _pat) = + match path with + | SyntaxNode.SynMemberDefn _ as node :: path -> + match folder state path node with + | Some state' -> + state <- state' + None + | None -> Some() + | _ -> None + + member _.VisitInterfaceSynMemberDefnType(path, _synType) = + match path with + | SyntaxNode.SynMemberDefn _ as node :: path -> + match folder state path node with + | Some state' -> + state <- state' + None + | None -> Some() + | _ -> None + } + + ignore (SyntaxTraversal.traverseUntil pick pos visitor ast) + state + + let foldWhile folder state (parsedInput: ParsedInput) = + let pickAll _ _ _ diveResults = + let rec loop diveResults = + match diveResults with | [] -> None | (_, project) :: rest -> ignore (project ()) @@ -1103,9 +1467,105 @@ module SyntaxTraversal = loop diveResults - ignore<'T option> (traverseUntil pick parseTree.Range.End visitor parseTree) + let ast = parsedInput.Contents + let m = (range0, ast) ||> List.fold (fun acc node -> unionRanges acc node.Range) + foldWhileImpl pickAll m.End folder state ast + + let tryPick chooser position (parsedInput: ParsedInput) = + let visitor = + { new SyntaxVisitorBase<'T>() with + member _.VisitExpr(path, _, defaultTraverse, expr) = + (match path with + | SyntaxNode.SynMemberDefn _ as parent :: parentPath -> chooser parentPath parent + | _ -> None) + |> Option.orElseWith (fun () -> chooser path (SyntaxNode.SynExpr expr)) + |> Option.orElseWith (fun () -> defaultTraverse expr) + + member _.VisitPat(path, defaultTraverse, pat) = + chooser path (SyntaxNode.SynPat pat) + |> Option.orElseWith (fun () -> defaultTraverse pat) + + member _.VisitType(path, defaultTraverse, synType) = + (match path with + | SyntaxNode.SynMemberDefn _ | SyntaxNode.SynMemberSig _ as parent :: parentPath -> chooser parentPath parent + | _ -> None) + |> Option.orElseWith (fun () -> chooser path (SyntaxNode.SynType synType)) + |> Option.orElseWith (fun () -> defaultTraverse synType) + + member _.VisitModuleDecl(path, defaultTraverse, synModuleDecl) = + chooser path (SyntaxNode.SynModule synModuleDecl) + |> Option.orElseWith (fun () -> + match synModuleDecl with + | SynModuleDecl.Types(types, _) -> + let path = SyntaxNode.SynModule synModuleDecl :: path + types |> List.tryPick (SyntaxNode.SynTypeDefn >> chooser path) + | _ -> None) + |> Option.orElseWith (fun () -> defaultTraverse synModuleDecl) + + member _.VisitModuleOrNamespace(path, synModuleOrNamespace) = + chooser path (SyntaxNode.SynModuleOrNamespace synModuleOrNamespace) + + member _.VisitMatchClause(path, defaultTraverse, matchClause) = + chooser path (SyntaxNode.SynMatchClause matchClause) + |> Option.orElseWith (fun () -> defaultTraverse matchClause) + + member _.VisitBinding(path, defaultTraverse, synBinding) = + (match path with + | SyntaxNode.SynMemberDefn _ as parent :: parentPath -> chooser parentPath parent + | _ -> None) + |> Option.orElseWith (fun () -> chooser path (SyntaxNode.SynBinding synBinding)) + |> Option.orElseWith (fun () -> defaultTraverse synBinding) + + member _.VisitModuleOrNamespaceSig(path, synModuleOrNamespaceSig) = + chooser path (SyntaxNode.SynModuleOrNamespaceSig synModuleOrNamespaceSig) + + member _.VisitModuleSigDecl(path, defaultTraverse, synModuleSigDecl) = + chooser path (SyntaxNode.SynModuleSigDecl synModuleSigDecl) + |> Option.orElseWith (fun () -> + match synModuleSigDecl with + | SynModuleSigDecl.Types(types, _) -> + let path = SyntaxNode.SynModuleSigDecl synModuleSigDecl :: path + types |> List.tryPick (SyntaxNode.SynTypeDefnSig >> chooser path) + | _ -> None) + |> Option.orElseWith (fun () -> defaultTraverse synModuleSigDecl) + + member _.VisitValSig(path, defaultTraverse, valSig) = + (match path with + | SyntaxNode.SynMemberSig _ as parent :: parentPath -> chooser parentPath parent + | _ -> None) + |> Option.orElseWith (fun () -> chooser path (SyntaxNode.SynValSig valSig)) + |> Option.orElseWith (fun () -> defaultTraverse valSig) + + member _.VisitSimplePats(path, _pat) = + match path with + | SyntaxNode.SynMemberDefn _ as node :: path -> chooser path node + | _ -> None - /// traverse an implementation file walking all the way down to SynExpr or TypeAbbrev at a particular location - /// - let Traverse (pos: pos, parseTree, visitor: SyntaxVisitorBase<'T>) = - traverseUntil pick pos visitor parseTree + member _.VisitInterfaceSynMemberDefnType(path, _synType) = + match path with + | SyntaxNode.SynMemberDefn _ as node :: path -> chooser path node + | _ -> None + } + + SyntaxTraversal.traverseUntil SyntaxTraversal.pick position visitor parsedInput.Contents + + let tryPickLast chooser position (parsedInput: ParsedInput) = + (None, parsedInput.Contents) + ||> foldWhileImpl SyntaxTraversal.pick position (fun prev path node -> + match chooser path node with + | Some _ as next -> Some next + | None -> Some prev) + + let tryNode position (parsedInput: ParsedInput) = + let Matching = Some + + (None, parsedInput.Contents) + ||> foldWhileImpl SyntaxTraversal.pick position (fun _prev path node -> + if rangeContainsPos node.Range position then + Some(Matching(node, path)) + else + None) + + let exists predicate position parsedInput = + tryPick (fun path node -> if predicate path node then Some() else None) position parsedInput + |> Option.isSome diff --git a/src/Compiler/Service/ServiceParseTreeWalk.fsi b/src/Compiler/Service/ServiceParseTreeWalk.fsi index ef118baf12e..86ca17380ee 100644 --- a/src/Compiler/Service/ServiceParseTreeWalk.fsi +++ b/src/Compiler/Service/ServiceParseTreeWalk.fsi @@ -5,7 +5,7 @@ namespace FSharp.Compiler.Syntax open FSharp.Compiler.Syntax open FSharp.Compiler.Text -/// Used to track route during traversal of syntax using SyntaxTraversal.Traverse +/// Represents a major syntax node in the untyped abstract syntax tree. [] type SyntaxNode = | SynPat of SynPat @@ -23,6 +23,11 @@ type SyntaxNode = | SynTypeDefnSig of SynTypeDefnSig | SynMemberSig of SynMemberSig + /// The range of the syntax node, inclusive of its contents. + member Range: range + +/// Represents the set of ancestor nodes traversed before reaching +/// the current node in a traversal of the untyped abstract syntax tree. type SyntaxVisitorPath = SyntaxNode list [] @@ -152,8 +157,8 @@ type SyntaxVisitorBase<'T> = default VisitRecordField: path: SyntaxVisitorPath * copyOpt: SynExpr option * recordField: SynLongIdent option -> 'T option - abstract VisitSimplePats: path: SyntaxVisitorPath * synPats: SynSimplePat list -> 'T option - default VisitSimplePats: path: SyntaxVisitorPath * synPats: SynSimplePat list -> 'T option + abstract VisitSimplePats: path: SyntaxVisitorPath * pat: SynPat -> 'T option + default VisitSimplePats: path: SyntaxVisitorPath * pat: SynPat -> 'T option abstract VisitType: path: SyntaxVisitorPath * defaultTraverse: (SynType -> 'T option) * synType: SynType -> 'T option @@ -199,6 +204,157 @@ module public SyntaxTraversal = val internal pick: pos: pos -> outerRange: range -> debugObj: obj -> diveResults: (range * (unit -> 'a option)) list -> 'a option - val internal traverseAll: visitor: SyntaxVisitorBase<'T> -> parseTree: ParsedInput -> unit - val Traverse: pos: pos * parseTree: ParsedInput * visitor: SyntaxVisitorBase<'T> -> 'T option + +/// +/// Holds operations for working with s +/// in the untyped abstract syntax tree (AST). +/// +[] +[] +module SyntaxNode = + /// + /// Extracts the , if any, + /// from the given . + /// + val (|Attributes|): node: SyntaxNode -> SynAttributes + +/// +/// Holds operations for working with the +/// untyped abstract syntax tree (). +/// +[] +[] +module ParsedInput = + /// + /// Applies the given predicate to each node of the AST and its context (path) + /// down to a given position, returning true if a matching node is found, otherwise false. + /// Traversal is short-circuited if no matching node is found through the given position. + /// + /// The predicate to match each node against. + /// The position in the input file down to which to apply the function. + /// The AST to search. + /// True if a matching node is found, or false if no matching node is found. + /// + /// + /// let isInTypeDefn = + /// (pos, parsedInput) + /// ||> ParsedInput.exists (fun _path node -> + /// match node with + /// | SyntaxNode.SynTypeDefn _ -> true + /// | _ -> false) + /// + /// + val exists: + predicate: (SyntaxVisitorPath -> SyntaxNode -> bool) -> position: pos -> parsedInput: ParsedInput -> bool + + /// + /// Applies a function to each node of the AST and its context (path), + /// threading an accumulator through the computation. + /// + /// The function to use to update the state given each node and its context. + /// The initial state. + /// The AST to fold over. + /// The final state. + /// + /// + /// let unnecessaryParentheses = + /// (HashSet Range.comparer, parsedInput) ||> ParsedInput.fold (fun acc path node -> + /// match node with + /// | SyntaxNode.SynExpr (SynExpr.Paren (expr = inner; rightParenRange = Some _; range = range)) when + /// not (SynExpr.shouldBeParenthesizedInContext getLineString path inner) + /// -> + /// ignore (acc.Add range) + /// acc + /// + /// | SyntaxNode.SynPat (SynPat.Paren (inner, range)) when + /// not (SynPat.shouldBeParenthesizedInContext path inner) + /// -> + /// ignore (acc.Add range) + /// acc + /// + /// | _ -> acc) + /// + /// + val fold: + folder: ('State -> SyntaxVisitorPath -> SyntaxNode -> 'State) -> + state: 'State -> + parsedInput: ParsedInput -> + 'State + + /// + /// Applies a function to each node of the AST and its context (path) + /// until the folder returns None, threading an accumulator through the computation. + /// + /// The function to use to update the state given each node and its context, or to stop traversal by returning None. + /// The initial state. + /// The AST to fold over. + /// The final state. + val foldWhile: + folder: ('State -> SyntaxVisitorPath -> SyntaxNode -> 'State option) -> + state: 'State -> + parsedInput: ParsedInput -> + 'State + + /// + /// Dives to the deepest node that contains the given position, + /// returning the node and its path if found, or None if no + /// node contains the position. + /// + /// The position in the input file down to which to dive. + /// The AST to search. + /// The deepest node containing the given position, along with the path taken through the node's ancestors to find it. + val tryNode: position: pos -> parsedInput: ParsedInput -> (SyntaxNode * SyntaxVisitorPath) option + + /// + /// Applies the given function to each node of the AST and its context (path) + /// down to a given position, returning Some x for the first node + /// for which the function returns Some x for some value x, otherwise None. + /// Traversal is short-circuited if no matching node is found through the given position. + /// + /// The function to apply to each node and its context to derive an optional value. + /// The position in the input file down to which to apply the function. + /// The AST to search. + /// The first value for which the function returns Some, or None if no matching node is found. + /// + /// + /// let range = + /// (pos, parsedInput) ||> ParsedInput.tryPick (fun _path node -> + /// match node with + /// | SyntaxNode.SynExpr (SynExpr.InterpolatedString (range = range)) when + /// rangeContainsPos range pos + /// -> Some range + /// | _ -> None) + /// + /// + val tryPick: + chooser: (SyntaxVisitorPath -> SyntaxNode -> 'T option) -> + position: pos -> + parsedInput: ParsedInput -> + 'T option + + /// + /// Applies the given function to each node of the AST and its context (path) + /// down to a given position, returning Some x for the last (deepest) node + /// for which the function returns Some x for some value x, otherwise None. + /// Traversal is short-circuited if no matching node is found through the given position. + /// + /// The function to apply to each node and its context to derive an optional value. + /// The position in the input file down to which to apply the function. + /// The AST to search. + /// The last (deepest) value for which the function returns Some, or None if no matching node is found. + /// + /// + /// let range = + /// (pos, parsedInput) + /// ||> ParsedInput.tryPickLast (fun path node -> + /// match node, path with + /// | FuncIdent range -> Some range + /// | _ -> None) + /// + /// + val tryPickLast: + chooser: (SyntaxVisitorPath -> SyntaxNode -> 'T option) -> + position: pos -> + parsedInput: ParsedInput -> + 'T option diff --git a/src/Compiler/Service/ServiceParsedInputOps.fs b/src/Compiler/Service/ServiceParsedInputOps.fs index 421ccc3fb0d..617cd2bdf00 100644 --- a/src/Compiler/Service/ServiceParsedInputOps.fs +++ b/src/Compiler/Service/ServiceParsedInputOps.fs @@ -891,9 +891,8 @@ module ParsedInput = | None, Some binding -> walkBinding binding | Some getBinding, Some setBinding -> walkBinding getBinding |> Option.orElseWith (fun () -> walkBinding setBinding) - | SynMemberDefn.ImplicitCtor(attributes = Attributes attrs; ctorArgs = SynSimplePats.SimplePats(pats = simplePats)) -> - List.tryPick walkAttribute attrs - |> Option.orElseWith (fun () -> List.tryPick walkSimplePat simplePats) + | SynMemberDefn.ImplicitCtor(attributes = Attributes attrs; ctorArgs = pat) -> + List.tryPick walkAttribute attrs |> Option.orElseWith (fun _ -> walkPat pat) | SynMemberDefn.ImplicitInherit(t, e, _, _) -> walkType t |> Option.orElseWith (fun () -> walkExpr e) @@ -1580,25 +1579,36 @@ module ParsedInput = | [] when range.StartLine = pos.Line -> Some CompletionContext.Invalid | _ -> None - member _.VisitSimplePats(_, pats) = + member _.VisitSimplePats(_, pat) = // Lambdas and their patterns are processed above in VisitExpr, // so VisitSimplePats is only called for primary constructors - pats - |> List.tryPick (fun pat -> - match pat with - // type C (x| ) - | SynSimplePat.Id(range = range) when rangeContainsPos range pos -> Some CompletionContext.Invalid - | SynSimplePat.Typed(pat = SynSimplePat.Id(range = idRange); targetType = synType) -> - // type C (x|: int) -> - if rangeContainsPos idRange pos then - Some CompletionContext.Invalid - // type C (x: int|) -> - elif rangeContainsPos synType.Range pos then - Some CompletionContext.Type - else - None - | _ -> None) + let rec loop (pat: SynPat) = + if not (rangeContainsPos pat.Range pos) then + None + else + + match pat with + // type C (x{caret} ) + | SynPat.Named _ + | SynPat.Const(SynConst.Unit, _) -> Some CompletionContext.Invalid + + | SynPat.Attrib(pat, _, _) + | SynPat.Paren(pat, _) -> loop pat + + | SynPat.Tuple(_, pats, _, _) -> List.tryPick loop pats + + | SynPat.Typed(pat, synType, _) -> + // type C (x: int{caret}) -> + if rangeContainsPos synType.Range pos then + Some CompletionContext.Type + else + // type C (x{caret}: int) -> + loop pat + + | _ -> None + + loop pat member _.VisitPat(_, defaultTraverse, pat) = TryGetCompletionContextInPattern false pat None pos @@ -2091,9 +2101,9 @@ module ParsedInput = | SynMemberDefn.GetSetMember(getBinding, setBinding, _, _) -> Option.iter walkBinding getBinding Option.iter walkBinding setBinding - | SynMemberDefn.ImplicitCtor(attributes = Attributes attrs; ctorArgs = SynSimplePats.SimplePats(pats = simplePats)) -> + | SynMemberDefn.ImplicitCtor(attributes = Attributes attrs; ctorArgs = pat) -> List.iter walkAttribute attrs - List.iter walkSimplePat simplePats + walkPat pat | SynMemberDefn.ImplicitInherit(t, e, _, _) -> walkType t walkExpr e diff --git a/src/Compiler/Service/SynExpr.fs b/src/Compiler/Service/SynExpr.fs new file mode 100644 index 00000000000..0df9a1a1c17 --- /dev/null +++ b/src/Compiler/Service/SynExpr.fs @@ -0,0 +1,931 @@ +namespace FSharp.Compiler.Syntax + +open System +open FSharp.Compiler.SyntaxTrivia +open FSharp.Compiler.Text + +[] +[] +module SynExpr = + let (|Last|) = List.last + + /// Matches if the two values refer to the same object. + [] + let inline (|Is|_|) (inner1: 'a) (inner2: 'a) = + if obj.ReferenceEquals(inner1, inner2) then + ValueSome Is + else + ValueNone + + /// Represents a symbolic infix operator with the precedence of *, /, or %. + /// All instances of this type are considered equal. + [] + type MulDivMod = + | Mul + | Div + | Mod + + member _.CompareTo(_other: MulDivMod) = 0 + override this.Equals obj = this.CompareTo(unbox obj) = 0 + override _.GetHashCode() = 0 + + interface IComparable with + member this.CompareTo obj = this.CompareTo(unbox obj) + + /// Represents a symbolic infix operator with the precedence of + or -. + /// All instances of this type are considered equal. + [] + type AddSub = + | Add + | Sub + + member _.CompareTo(_other: AddSub) = 0 + override this.Equals obj = this.CompareTo(unbox obj) = 0 + override _.GetHashCode() = 0 + + interface IComparable with + member this.CompareTo obj = this.CompareTo(unbox obj) + + /// Holds a symbolic operator's original notation. + /// Equality is based on the contents of the string. + /// Comparison always returns 0. + [] + type OriginalNotation = + | OriginalNotation of string + + member _.CompareTo(_other: OriginalNotation) = 0 + + override this.Equals obj = + match this, obj with + | OriginalNotation this, (:? OriginalNotation as OriginalNotation other) -> String.Equals(this, other, StringComparison.Ordinal) + | _ -> false + + override this.GetHashCode() = + match this with + | OriginalNotation notation -> notation.GetHashCode() + + interface IComparable with + member this.CompareTo obj = this.CompareTo(unbox obj) + + /// Represents an expression's precedence. + /// Comparison is based only on the precedence case. + /// Equality considers the embedded original notation, if any. + /// + /// For example: + /// + /// compare (AddSub (Add, OriginalNotation "+")) (AddSub (Add, OriginalNotation "++")) = 0 + /// + /// but + /// + /// AddSub (Add, OriginalNotation "+") <> AddSub (Add, OriginalNotation "++") + type Precedence = + /// yield, yield!, return, return! + | Low + + /// <- + | Set + + /// := + | ColonEquals + + /// , + | Comma + + /// or, || + /// + /// Refers to the exact operators or and ||. + /// Instances with leading dots or question marks or trailing characters are parsed as Bar instead. + | BarBar of OriginalNotation + + /// &, && + /// + /// Refers to the exact operators & and &&. + /// Instances with leading dots or question marks or trailing characters are parsed as Amp instead. + | AmpAmp of OriginalNotation + + /// :>, :?> + | UpcastDowncast + + /// =…, |…, &…, $…, >…, <…, !=… + | Relational of OriginalNotation + + /// ^…, @… + | HatAt + + /// :: + | Cons + + /// :? + | TypeTest + + /// +…, -… + | AddSub of AddSub * OriginalNotation + + /// *…, /…, %… + | MulDivMod of MulDivMod * OriginalNotation + + /// **… + | Exp + + /// - x + | UnaryPrefix + + /// f x + | Apply + + /// -x, !… x, ~~… x + | High + + // x.y + | Dot + + /// Associativity/association. + type Assoc = + /// Non-associative or no association. + | Non + + /// Left-associative or left-hand association. + | Left + + /// Right-associative or right-hand association. + | Right + + module Assoc = + let ofPrecedence precedence = + match precedence with + | Low -> Non + | Set -> Non + | ColonEquals -> Right + | Comma -> Non + | BarBar _ -> Left + | AmpAmp _ -> Left + | UpcastDowncast -> Right + | Relational _ -> Left + | HatAt -> Right + | Cons -> Right + | TypeTest -> Non + | AddSub _ -> Left + | MulDivMod _ -> Left + | Exp -> Right + | UnaryPrefix -> Left + | Apply -> Left + | High -> Left + | Dot -> Left + + /// See atomicExprAfterType in pars.fsy. + [] + let (|AtomicExprAfterType|_|) expr = + match expr with + | SynExpr.Paren _ + | SynExpr.Quote _ + | SynExpr.Const _ + | SynExpr.Tuple(isStruct = true) + | SynExpr.Record _ + | SynExpr.AnonRecd _ + | SynExpr.InterpolatedString _ + | SynExpr.Null _ + | SynExpr.ArrayOrList(isArray = true) + | SynExpr.ArrayOrListComputed(isArray = true) -> ValueSome AtomicExprAfterType + | _ -> ValueNone + + /// Matches if the given expression represents a high-precedence + /// function application, e.g., + /// + /// f x + /// + /// (+) x y + [] + let (|HighPrecedenceApp|_|) expr = + match expr with + | SynExpr.App(isInfix = false; funcExpr = SynExpr.Ident _) + | SynExpr.App(isInfix = false; funcExpr = SynExpr.LongIdent _) + | SynExpr.App(isInfix = false; funcExpr = SynExpr.App(isInfix = false)) -> ValueSome HighPrecedenceApp + | _ -> ValueNone + + module FuncExpr = + /// Matches when the given funcExpr is a direct application + /// of a symbolic operator, e.g., -, _not_ (~-). + [] + let (|SymbolicOperator|_|) funcExpr = + match funcExpr with + | SynExpr.LongIdent(longDotId = SynLongIdent(trivia = trivia)) -> + let rec tryPick = + function + | [] -> ValueNone + | Some(IdentTrivia.OriginalNotation op) :: _ -> ValueSome op + | _ :: rest -> tryPick rest + + tryPick trivia + | _ -> ValueNone + + /// Matches when the given expression is a prefix operator application, e.g., + /// + /// -x + /// + /// ~~~x + [] + let (|PrefixApp|_|) expr : Precedence voption = + match expr with + | SynExpr.App(isInfix = false; funcExpr = funcExpr & FuncExpr.SymbolicOperator op; argExpr = argExpr) -> + if funcExpr.Range.IsAdjacentTo argExpr.Range then + ValueSome High + else + assert (op.Length > 0) + + match op[0] with + | '!' + | '~' -> ValueSome High + | _ -> ValueSome UnaryPrefix + + | SynExpr.AddressOf(expr = expr; opRange = opRange) -> + if opRange.IsAdjacentTo expr.Range then + ValueSome High + else + ValueSome UnaryPrefix + + | _ -> ValueNone + + /// Tries to parse the given original notation as a symbolic infix operator. + [] + let (|SymbolPrec|_|) (originalNotation: string) = + // Trim any leading dots or question marks from the given symbolic operator. + // Leading dots or question marks have no effect on operator precedence or associativity + // with the exception of &, &&, and ||. + let ignoredLeadingChars = ".?".AsSpan() + let trimmed = originalNotation.AsSpan().TrimStart ignoredLeadingChars + assert (trimmed.Length > 0) + + match trimmed[0], originalNotation with + | _, ":=" -> ValueSome ColonEquals + | _, ("||" | "or") -> ValueSome(BarBar(OriginalNotation originalNotation)) + | _, ("&" | "&&") -> ValueSome(AmpAmp(OriginalNotation originalNotation)) + | '|', _ + | '&', _ + | '<', _ + | '>', _ + | '=', _ + | '$', _ -> ValueSome(Relational(OriginalNotation originalNotation)) + | '!', _ when trimmed.Length > 1 && trimmed[1] = '=' -> ValueSome(Relational(OriginalNotation originalNotation)) + | '^', _ + | '@', _ -> ValueSome HatAt + | _, "::" -> ValueSome Cons + | '+', _ -> ValueSome(AddSub(Add, OriginalNotation originalNotation)) + | '-', _ -> ValueSome(AddSub(Sub, OriginalNotation originalNotation)) + | '/', _ -> ValueSome(MulDivMod(Div, OriginalNotation originalNotation)) + | '%', _ -> ValueSome(MulDivMod(Mod, OriginalNotation originalNotation)) + | '*', _ when trimmed.Length > 1 && trimmed[1] = '*' -> ValueSome Exp + | '*', _ -> ValueSome(MulDivMod(Mul, OriginalNotation originalNotation)) + | _ -> ValueNone + + [] + let (|Contains|_|) (c: char) (s: string) = + if s.IndexOf c >= 0 then ValueSome Contains else ValueNone + + /// Any expressions in which the removal of parens would + /// lead to something like the following that would be + /// confused by the parser with a type parameter application: + /// + /// xz + /// + /// xz + [] + let rec (|ConfusableWithTypeApp|_|) synExpr = + match synExpr with + | SynExpr.Paren(expr = ConfusableWithTypeApp) + | SynExpr.App(funcExpr = ConfusableWithTypeApp) + | SynExpr.App(isInfix = true; funcExpr = FuncExpr.SymbolicOperator(Contains '>'); argExpr = ConfusableWithTypeApp) -> + ValueSome ConfusableWithTypeApp + | SynExpr.App(isInfix = true; funcExpr = funcExpr & FuncExpr.SymbolicOperator(Contains '<'); argExpr = argExpr) when + argExpr.Range.IsAdjacentTo funcExpr.Range + -> + ValueSome ConfusableWithTypeApp + | SynExpr.Tuple(exprs = exprs) -> + let rec anyButLast = + function + | _ :: [] + | [] -> ValueNone + | ConfusableWithTypeApp :: _ -> ValueSome ConfusableWithTypeApp + | _ :: tail -> anyButLast tail + + anyButLast exprs + | _ -> ValueNone + + /// Matches when the expression represents the infix application of a symbolic operator. + /// + /// (x λ y) ρ z + /// + /// x λ (y ρ z) + [] + let (|InfixApp|_|) synExpr : struct (Precedence * Assoc) voption = + match synExpr with + | SynExpr.App(funcExpr = SynExpr.App(isInfix = true; funcExpr = FuncExpr.SymbolicOperator(SymbolPrec prec))) -> + ValueSome(prec, Right) + | SynExpr.App(isInfix = true; funcExpr = FuncExpr.SymbolicOperator(SymbolPrec prec)) -> ValueSome(prec, Left) + | SynExpr.Upcast _ + | SynExpr.Downcast _ -> ValueSome(UpcastDowncast, Left) + | SynExpr.TypeTest _ -> ValueSome(TypeTest, Left) + | _ -> ValueNone + + /// Returns the given expression's precedence and the side of the inner expression, + /// if applicable. + [] + let (|OuterBinaryExpr|_|) inner outer : struct (Precedence * Assoc) voption = + match outer with + | SynExpr.YieldOrReturn _ + | SynExpr.YieldOrReturnFrom _ -> ValueSome(Low, Right) + | SynExpr.Tuple(exprs = SynExpr.Paren(expr = Is inner) :: _) -> ValueSome(Comma, Left) + | SynExpr.Tuple _ -> ValueSome(Comma, Right) + | InfixApp(Cons, side) -> ValueSome(Cons, side) + | SynExpr.Assert _ + | SynExpr.Lazy _ + | SynExpr.InferredUpcast _ + | SynExpr.InferredDowncast _ -> ValueSome(Apply, Non) + | PrefixApp prec -> ValueSome(prec, Non) + | InfixApp(prec, side) -> ValueSome(prec, side) + | SynExpr.App(argExpr = SynExpr.ComputationExpr _) -> ValueSome(UnaryPrefix, Left) + | SynExpr.App(funcExpr = SynExpr.Paren(expr = SynExpr.App _)) -> ValueSome(Apply, Left) + | SynExpr.App _ -> ValueSome(Apply, Non) + | SynExpr.DotSet(targetExpr = SynExpr.Paren(expr = Is inner)) -> ValueSome(Dot, Left) + | SynExpr.DotSet(rhsExpr = SynExpr.Paren(expr = Is inner)) -> ValueSome(Set, Right) + | SynExpr.DotIndexedSet(objectExpr = SynExpr.Paren(expr = Is inner)) + | SynExpr.DotNamedIndexedPropertySet(targetExpr = SynExpr.Paren(expr = Is inner)) -> ValueSome(Dot, Left) + | SynExpr.DotIndexedSet(valueExpr = SynExpr.Paren(expr = Is inner)) + | SynExpr.DotNamedIndexedPropertySet(rhsExpr = SynExpr.Paren(expr = Is inner)) -> ValueSome(Set, Right) + | SynExpr.LongIdentSet(expr = SynExpr.Paren(expr = Is inner)) -> ValueSome(Set, Right) + | SynExpr.Set _ -> ValueSome(Set, Non) + | SynExpr.DotGet _ -> ValueSome(Dot, Left) + | SynExpr.DotIndexedGet(objectExpr = SynExpr.Paren(expr = Is inner)) -> ValueSome(Dot, Left) + | _ -> ValueNone + + /// Matches a SynExpr.App nested in a sequence of dot-gets. + /// + /// x.M.N().O + [] + let (|NestedApp|_|) expr = + let rec loop = + function + | SynExpr.DotGet(expr = expr) + | SynExpr.DotIndexedGet(objectExpr = expr) -> loop expr + | SynExpr.App _ -> ValueSome NestedApp + | _ -> ValueNone + + loop expr + + /// Returns the given expression's precedence, if applicable. + [] + let (|InnerBinaryExpr|_|) expr : Precedence voption = + match expr with + | SynExpr.Tuple(isStruct = false) -> ValueSome Comma + | SynExpr.DotGet(expr = NestedApp) + | SynExpr.DotIndexedGet(objectExpr = NestedApp) -> ValueSome Apply + | SynExpr.DotGet _ + | SynExpr.DotIndexedGet _ -> ValueSome Dot + | PrefixApp prec -> ValueSome prec + | InfixApp(prec, _) -> ValueSome prec + | SynExpr.App _ + | SynExpr.Assert _ + | SynExpr.Lazy _ + | SynExpr.For _ + | SynExpr.ForEach _ + | SynExpr.While _ + | SynExpr.Do _ + | SynExpr.New _ + | SynExpr.InferredUpcast _ + | SynExpr.InferredDowncast _ -> ValueSome Apply + | SynExpr.DotIndexedSet _ + | SynExpr.DotNamedIndexedPropertySet _ + | SynExpr.DotSet _ -> ValueSome Set + | _ -> ValueNone + + module Dangling = + /// Returns the first matching nested right-hand target expression, if any. + let private dangling (target: SynExpr -> SynExpr option) = + let (|Target|_|) = target + + let rec loop expr = + match expr with + | Target expr -> ValueSome expr + | SynExpr.Tuple(isStruct = false; exprs = Last expr) + | SynExpr.App(argExpr = expr) + | SynExpr.IfThenElse(elseExpr = Some expr) + | SynExpr.IfThenElse(ifExpr = expr) + | SynExpr.Sequential(expr2 = expr) + | SynExpr.YieldOrReturn(expr = expr) + | SynExpr.YieldOrReturnFrom(expr = expr) + | SynExpr.Set(rhsExpr = expr) + | SynExpr.DotSet(rhsExpr = expr) + | SynExpr.DotNamedIndexedPropertySet(rhsExpr = expr) + | SynExpr.DotIndexedSet(valueExpr = expr) + | SynExpr.LongIdentSet(expr = expr) + | SynExpr.LetOrUse(body = expr) + | SynExpr.Lambda(body = expr) + | SynExpr.Match(clauses = Last(SynMatchClause(resultExpr = expr))) + | SynExpr.MatchLambda(matchClauses = Last(SynMatchClause(resultExpr = expr))) + | SynExpr.MatchBang(clauses = Last(SynMatchClause(resultExpr = expr))) + | SynExpr.TryWith(withCases = Last(SynMatchClause(resultExpr = expr))) + | SynExpr.TryFinally(finallyExpr = expr) -> loop expr + | _ -> ValueNone + + loop + + /// Matches a dangling if-then construct. + [] + let (|IfThen|_|) = + dangling (function + | SynExpr.IfThenElse _ as expr -> Some expr + | _ -> None) + + /// Matches a dangling sequential expression. + [] + let (|Sequential|_|) = + dangling (function + | SynExpr.Sequential _ as expr -> Some expr + | _ -> None) + + /// Matches a dangling try-with or try-finally construct. + [] + let (|Try|_|) = + dangling (function + | SynExpr.TryWith _ + | SynExpr.TryFinally _ as expr -> Some expr + | _ -> None) + + /// Matches a dangling match-like construct. + [] + let (|Match|_|) = + dangling (function + | SynExpr.Match _ + | SynExpr.MatchBang _ + | SynExpr.MatchLambda _ + | SynExpr.TryWith _ + | SynExpr.Lambda _ as expr -> Some expr + | _ -> None) + + /// Matches a nested dangling construct that could become problematic + /// if the surrounding parens were removed. + [] + let (|Problematic|_|) = + dangling (function + | SynExpr.Lambda _ + | SynExpr.MatchLambda _ + | SynExpr.Match _ + | SynExpr.MatchBang _ + | SynExpr.TryWith _ + | SynExpr.TryFinally _ + | SynExpr.IfThenElse _ + | SynExpr.Sequential _ + | SynExpr.LetOrUse _ + | SynExpr.Set _ + | SynExpr.LongIdentSet _ + | SynExpr.DotIndexedSet _ + | SynExpr.DotNamedIndexedPropertySet _ + | SynExpr.DotSet _ + | SynExpr.NamedIndexedPropertySet _ as expr -> Some expr + | _ -> None) + + /// Indicates whether the expression with the given range + /// includes indentation that would be invalid + /// in context if it were not wrapped in parentheses. + let containsSensitiveIndentation (getSourceLineStr: int -> string) outerOffsidesColumn (range: range) = + let startLine = range.StartLine + let endLine = range.EndLine + + if startLine = endLine then + range.StartColumn <= outerOffsidesColumn + else + let rec loop offsides lineNo startCol = + if lineNo <= endLine then + let line = getSourceLineStr lineNo + + match offsides with + | ValueNone -> + let i = line.AsSpan(startCol).IndexOfAnyExcept(' ', ')') + + if i >= 0 then + let newOffsides = i + startCol + + newOffsides <= outerOffsidesColumn + || loop (ValueSome newOffsides) (lineNo + 1) 0 + else + loop offsides (lineNo + 1) 0 + + | ValueSome offsidesCol -> + let i = line.AsSpan(0, min offsidesCol line.Length).IndexOfAnyExcept(' ', ')') + + if i >= 0 && i < offsidesCol then + let slice = line.AsSpan(i, min (offsidesCol - i) (line.Length - i)) + let j = slice.IndexOfAnyExcept("*/%-+:^@><=!|0$.?".AsSpan()) + + let lo = i + (if j >= 0 && slice[j] = ' ' then j else 0) + + lo < offsidesCol - 1 + || lo <= outerOffsidesColumn + || loop offsides (lineNo + 1) 0 + else + loop offsides (lineNo + 1) 0 + else + false + + loop ValueNone startLine range.StartColumn + + let rec shouldBeParenthesizedInContext (getSourceLineStr: int -> string) path expr : bool = + let shouldBeParenthesizedInContext = shouldBeParenthesizedInContext getSourceLineStr + let containsSensitiveIndentation = containsSensitiveIndentation getSourceLineStr + + // Matches if the given expression starts with a symbol, e.g., <@ … @>, $"…", @"…", +1, -1… + let (|StartsWithSymbol|_|) = + let (|TextStartsWith|) (m: range) = + let line = getSourceLineStr m.StartLine + line[m.StartColumn] + + let (|StartsWith|) (s: string) = s[0] + + function + | SynExpr.Quote _ + | SynExpr.InterpolatedString _ + | SynExpr.Const(SynConst.String(synStringKind = SynStringKind.Verbatim), _) + | SynExpr.Const(SynConst.Byte _, TextStartsWith '+') + | SynExpr.Const(SynConst.UInt16 _, TextStartsWith '+') + | SynExpr.Const(SynConst.UInt32 _, TextStartsWith '+') + | SynExpr.Const(SynConst.UInt64 _, TextStartsWith '+') + | SynExpr.Const(SynConst.UIntPtr _, TextStartsWith '+') + | SynExpr.Const(SynConst.SByte _, TextStartsWith('-' | '+')) + | SynExpr.Const(SynConst.Int16 _, TextStartsWith('-' | '+')) + | SynExpr.Const(SynConst.Int32 _, TextStartsWith('-' | '+')) + | SynExpr.Const(SynConst.Int64 _, TextStartsWith('-' | '+')) + | SynExpr.Const(SynConst.IntPtr _, TextStartsWith('-' | '+')) + | SynExpr.Const(SynConst.Decimal _, TextStartsWith('-' | '+')) + | SynExpr.Const(SynConst.Double _, TextStartsWith('-' | '+')) + | SynExpr.Const(SynConst.Single _, TextStartsWith('-' | '+')) + | SynExpr.Const(SynConst.Measure(_, TextStartsWith('-' | '+'), _, _), _) + | SynExpr.Const(SynConst.UserNum(StartsWith('-' | '+'), _), _) -> Some StartsWithSymbol + | _ -> None + + // Matches if the given expression is a numeric literal + // that it is safe to "dot into," e.g., 1l, 0b1, 1e10, 1d, 1.0… + let (|DotSafeNumericLiteral|_|) = + /// 1l, 1d, 0b1, 0x1, 0o1, 1e10… + let (|TextContainsLetter|_|) (m: range) = + let line = getSourceLineStr m.StartLine + let span = line.AsSpan(m.StartColumn, m.EndColumn - m.StartColumn) + + if span.LastIndexOfAnyInRange('A', 'z') >= 0 then + Some TextContainsLetter + else + None + + // 1.0… + let (|TextEndsWithNumber|_|) (m: range) = + let line = getSourceLineStr m.StartLine + let span = line.AsSpan(m.StartColumn, m.EndColumn - m.StartColumn) + + if Char.IsDigit span[span.Length - 1] then + Some TextEndsWithNumber + else + None + + function + | SynExpr.Const(SynConst.Byte _, _) + | SynExpr.Const(SynConst.UInt16 _, _) + | SynExpr.Const(SynConst.UInt32 _, _) + | SynExpr.Const(SynConst.UInt64 _, _) + | SynExpr.Const(SynConst.UIntPtr _, _) + | SynExpr.Const(SynConst.SByte _, _) + | SynExpr.Const(SynConst.Int16 _, _) + | SynExpr.Const(SynConst.Int32 _, TextContainsLetter) + | SynExpr.Const(SynConst.Int64 _, _) + | SynExpr.Const(SynConst.IntPtr _, _) + | SynExpr.Const(SynConst.Decimal _, _) + | SynExpr.Const(SynConst.Double _, (TextEndsWithNumber | TextContainsLetter)) + | SynExpr.Const(SynConst.Single _, _) + | SynExpr.Const(SynConst.Measure _, _) + | SynExpr.Const(SynConst.UserNum _, _) -> Some DotSafeNumericLiteral + | _ -> None + + match expr, path with + // Parens must stay around binary equals expressions in argument + // position lest they be interpreted as named argument assignments: + // + // o.M((x = y)) + // o.N((x = y), z) + | SynExpr.Paren(expr = InfixApp(Relational(OriginalNotation "="), _)), + SyntaxNode.SynExpr(SynExpr.App(funcExpr = SynExpr.LongIdent _)) :: _ + | InfixApp(Relational(OriginalNotation "="), _), + SyntaxNode.SynExpr(SynExpr.Paren _) :: SyntaxNode.SynExpr(SynExpr.App(funcExpr = SynExpr.LongIdent _)) :: _ + | InfixApp(Relational(OriginalNotation "="), _), + SyntaxNode.SynExpr(SynExpr.Tuple(isStruct = false)) :: SyntaxNode.SynExpr(SynExpr.Paren _) :: SyntaxNode.SynExpr(SynExpr.App( + funcExpr = SynExpr.LongIdent _)) :: _ -> true + + // Already parenthesized. + | _, SyntaxNode.SynExpr(SynExpr.Paren _) :: _ -> false + + // Parens must stay around indentation that would otherwise be invalid: + // + // let _ = (x + // +y) + | _, SyntaxNode.SynBinding(SynBinding(trivia = trivia)) :: _ when + containsSensitiveIndentation trivia.LeadingKeyword.Range.StartColumn expr.Range + -> + true + + // Parens must stay around indentation that would otherwise be invalid: + // + // return ( + // x + // ) + | _, SyntaxNode.SynExpr outer :: _ when containsSensitiveIndentation outer.Range.StartColumn expr.Range -> true + + // Check for nested matches, e.g., + // + // match … with … -> (…, match … with … -> … | … -> …) | … -> … + | _, SyntaxNode.SynMatchClause _ :: path -> shouldBeParenthesizedInContext path expr + + // We always need parens for trait calls, e.g., + // + // let inline f x = (^a : (static member Parse : string -> ^a) x) + | SynExpr.TraitCall _, _ -> true + + // Don't touch library-only stuff: + // + // (# "ldlen.multi 2 0" array : int #) + | SynExpr.LibraryOnlyILAssembly _, _ + | SynExpr.LibraryOnlyStaticOptimization _, _ + | SynExpr.LibraryOnlyUnionCaseFieldGet _, _ + | SynExpr.LibraryOnlyUnionCaseFieldSet _, _ -> true + + // Parens are otherwise never required for binding bodies or for top-level expressions, e.g., + // + // let x = (…) + // _.member X = (…) + // (printfn "Hello, world.") + | _, SyntaxNode.SynBinding _ :: _ + | _, SyntaxNode.SynModule _ :: _ -> false + + // Parens must be kept when there is a high-precedence function application + // before a prefix operator application before another expression that starts with a symbol, e.g., + // + // id -(-x) + // id -(-1y) + // id -($"") + // id -(@"") + // id -(<@ ValueNone @>) + // let (~+) _ = true in assert +($"{true}") + | (PrefixApp _ | StartsWithSymbol), + SyntaxNode.SynExpr(SynExpr.App _) :: SyntaxNode.SynExpr(HighPrecedenceApp | SynExpr.Assert _ | SynExpr.InferredUpcast _ | SynExpr.InferredDowncast _) :: _ -> + true + + // Parens are never required around suffixed or infixed numeric literals, e.g., + // + // (1l).ToString() + // (1uy).ToString() + // (0b1).ToString() + // (1e10).ToString() + // (1.0).ToString() + | DotSafeNumericLiteral, _ -> false + + // Parens are required around bare decimal ints or doubles ending + // in dots when being dotted into, e.g., + // + // (1).ToString() + // (1.).ToString() + | SynExpr.Const(constant = SynConst.Int32 _ | SynConst.Double _), SyntaxNode.SynExpr(SynExpr.DotGet _) :: _ -> true + + // Parens are required around join conditions: + // + // join … on (… = …) + | SynExpr.App _, SyntaxNode.SynExpr(SynExpr.App _) :: SyntaxNode.SynExpr(SynExpr.JoinIn _) :: _ -> true + + // Parens are not required around a few anointed expressions after inherit: + // + // inherit T(3) + // inherit T(null) + // inherit T("") + // … + | AtomicExprAfterType, SyntaxNode.SynMemberDefn(SynMemberDefn.ImplicitInherit _) :: _ -> false + + // Parens are otherwise required in inherit T(x), etc. + | _, SyntaxNode.SynMemberDefn(SynMemberDefn.ImplicitInherit _) :: _ -> true + + // We can't remove parens when they're required for fluent calls: + // + // x.M(y).N z + // x.M(y).[z] + // _.M(x) + // (f x)[z] + // (f(x))[z] + // x.M(y)[z] + | _, SyntaxNode.SynExpr(SynExpr.App _) :: SyntaxNode.SynExpr(SynExpr.DotGet _ | SynExpr.DotIndexedGet _ | SynExpr.DotLambda _) :: _ + | SynExpr.App _, SyntaxNode.SynExpr(SynExpr.App(argExpr = SynExpr.ArrayOrListComputed(isArray = false))) :: _ + | _, + SyntaxNode.SynExpr(SynExpr.App _) :: SyntaxNode.SynExpr(SynExpr.App(argExpr = SynExpr.ArrayOrListComputed(isArray = false))) :: _ -> + true + + // The :: operator is parsed differently from other symbolic infix operators, + // so we need to give it special treatment. + + // Outer right: + // + // (x) :: xs + // (x * y) :: zs + // … + | _, + SyntaxNode.SynExpr(SynExpr.Tuple(isStruct = false; exprs = [ SynExpr.Paren _; _ ])) :: (SyntaxNode.SynExpr(SynExpr.App( + isInfix = true)) :: _ as path) -> shouldBeParenthesizedInContext path expr + + // Outer left: + // + // x :: (xs) + // x :: (ys @ zs) + // … + | argExpr, + SyntaxNode.SynExpr(SynExpr.Tuple(isStruct = false; exprs = [ _; SynExpr.Paren _ ])) :: SyntaxNode.SynExpr(SynExpr.App( + isInfix = true) as outer) :: path -> + shouldBeParenthesizedInContext + (SyntaxNode.SynExpr(SynExpr.App(ExprAtomicFlag.NonAtomic, false, outer, argExpr, outer.Range)) + :: path) + expr + + // Ordinary nested expressions. + | inner, SyntaxNode.SynExpr outer :: outerPath -> + let dangling expr = + match expr with + | Dangling.Problematic subExpr -> + match outer with + | SynExpr.Tuple(exprs = exprs) -> not (obj.ReferenceEquals(subExpr, List.last exprs)) + | InfixApp(_, Left) -> true + | _ -> shouldBeParenthesizedInContext outerPath subExpr + + | _ -> false + + let problematic (exprRange: range) (delimiterRange: range) = + exprRange.EndLine = delimiterRange.EndLine + && exprRange.EndColumn < delimiterRange.StartColumn + + let anyProblematic matchOrTryRange clauses = + let rec loop = + function + | [] -> false + | SynMatchClause(trivia = trivia) :: clauses -> + trivia.BarRange |> Option.exists (problematic matchOrTryRange) + || trivia.ArrowRange |> Option.exists (problematic matchOrTryRange) + || loop clauses + + loop clauses + + match outer, inner with + | ConfusableWithTypeApp, _ -> true + + | SynExpr.IfThenElse _, Dangling.Sequential _ -> true + + | SynExpr.IfThenElse(trivia = trivia), Dangling.IfThen ifThenElse when + problematic ifThenElse.Range trivia.ThenKeyword + || trivia.ElseKeyword |> Option.exists (problematic ifThenElse.Range) + -> + true + + | SynExpr.TryFinally(trivia = trivia), Dangling.Try tryExpr when problematic tryExpr.Range trivia.FinallyKeyword -> true + + | SynExpr.Match(clauses = clauses; trivia = { WithKeyword = withKeyword }), Dangling.Match matchOrTry when + problematic matchOrTry.Range withKeyword + || anyProblematic matchOrTry.Range clauses + -> + true + + | SynExpr.MatchBang(clauses = clauses; trivia = { WithKeyword = withKeyword }), Dangling.Match matchOrTry when + problematic matchOrTry.Range withKeyword + || anyProblematic matchOrTry.Range clauses + -> + true + + | SynExpr.MatchLambda(matchClauses = clauses), Dangling.Match matchOrTry when anyProblematic matchOrTry.Range clauses -> true + + | SynExpr.TryWith(withCases = clauses; trivia = trivia), Dangling.Match matchOrTry when + problematic matchOrTry.Range trivia.WithKeyword + || anyProblematic matchOrTry.Range clauses + -> + true + + | SynExpr.Sequential(expr1 = SynExpr.Paren(expr = Is inner); expr2 = expr2), Dangling.Problematic _ when + problematic inner.Range expr2.Range + -> + true + + | SynExpr.Record(copyInfo = Some(SynExpr.Paren(expr = Is inner), _)), Dangling.Problematic _ + | SynExpr.AnonRecd(copyInfo = Some(SynExpr.Paren(expr = Is inner), _)), Dangling.Problematic _ -> true + + | SynExpr.Record(recordFields = recordFields), Dangling.Problematic _ -> + let rec loop recordFields = + match recordFields with + | [] -> false + | SynExprRecordField(expr = Some(SynExpr.Paren(expr = Is inner)); blockSeparator = Some _) :: SynExprRecordField( + fieldName = SynLongIdent(id = id :: _), _) :: _ -> problematic inner.Range id.idRange + | _ :: recordFields -> loop recordFields + + loop recordFields + + | SynExpr.AnonRecd(recordFields = recordFields), Dangling.Problematic _ -> + let rec loop recordFields = + match recordFields with + | [] -> false + | (_, Some _blockSeparator, SynExpr.Paren(expr = Is inner)) :: (SynLongIdent(id = id :: _), _, _) :: _ -> + problematic inner.Range id.idRange + | _ :: recordFields -> loop recordFields + + loop recordFields + + | SynExpr.Paren _, SynExpr.Typed _ + | SynExpr.Quote _, SynExpr.Typed _ + | SynExpr.AnonRecd _, SynExpr.Typed _ + | SynExpr.Record _, SynExpr.Typed _ + | SynExpr.While(doExpr = SynExpr.Paren(expr = Is inner)), SynExpr.Typed _ + | SynExpr.WhileBang(doExpr = SynExpr.Paren(expr = Is inner)), SynExpr.Typed _ + | SynExpr.For(doBody = Is inner), SynExpr.Typed _ + | SynExpr.ForEach(bodyExpr = Is inner), SynExpr.Typed _ + | SynExpr.Match _, SynExpr.Typed _ + | SynExpr.Do _, SynExpr.Typed _ + | SynExpr.LetOrUse(body = Is inner), SynExpr.Typed _ + | SynExpr.TryWith _, SynExpr.Typed _ + | SynExpr.TryFinally _, SynExpr.Typed _ -> false + | _, SynExpr.Typed _ -> true + + | OuterBinaryExpr inner (outerPrecedence, side), InnerBinaryExpr innerPrecedence -> + let ambiguous = + match compare outerPrecedence innerPrecedence with + | 0 -> + match side, Assoc.ofPrecedence innerPrecedence with + | Non, _ + | _, Non + | Left, Right -> true + | Right, Right + | Left, Left -> false + | Right, Left -> + outerPrecedence <> innerPrecedence + || match outerPrecedence, innerPrecedence with + | _, MulDivMod(Div, _) + | _, MulDivMod(Mod, _) + | _, AddSub(Sub, _) -> true + | Relational _, Relational _ -> true + | _ -> false + + | c -> c > 0 + + ambiguous || dangling inner + + | OuterBinaryExpr inner (_, Right), (SynExpr.Sequential _ | SynExpr.LetOrUse(trivia = { InKeyword = None })) -> true + | OuterBinaryExpr inner (_, Right), inner -> dangling inner + + // new T(expr) + | SynExpr.New _, AtomicExprAfterType -> false + | SynExpr.New _, _ -> true + + // { inherit T(expr); … } + | SynExpr.Record(baseInfo = Some(_, SynExpr.Paren(expr = Is inner), _, _, _)), AtomicExprAfterType -> false + | SynExpr.Record(baseInfo = Some(_, SynExpr.Paren(expr = Is inner), _, _, _)), _ -> true + + | _, SynExpr.Paren _ + | _, SynExpr.Quote _ + | _, SynExpr.Const _ + | _, SynExpr.Tuple(isStruct = true) + | _, SynExpr.AnonRecd _ + | _, SynExpr.ArrayOrList _ + | _, SynExpr.Record _ + | _, SynExpr.ObjExpr _ + | _, SynExpr.ArrayOrListComputed _ + | _, SynExpr.ComputationExpr _ + | _, SynExpr.TypeApp _ + | _, SynExpr.Ident _ + | _, SynExpr.LongIdent _ + | _, SynExpr.DotGet _ + | _, SynExpr.DotLambda _ + | _, SynExpr.DotIndexedGet _ + | _, SynExpr.Null _ + | _, SynExpr.InterpolatedString _ + + | SynExpr.Paren _, _ + | SynExpr.Quote _, _ + | SynExpr.Typed _, _ + | SynExpr.AnonRecd _, _ + | SynExpr.Record _, _ + | SynExpr.ObjExpr _, _ + | SynExpr.While _, _ + | SynExpr.WhileBang _, _ + | SynExpr.For _, _ + | SynExpr.ForEach _, _ + | SynExpr.Lambda _, _ + | SynExpr.MatchLambda _, _ + | SynExpr.Match _, _ + | SynExpr.MatchBang _, _ + | SynExpr.LetOrUse _, _ + | SynExpr.LetOrUseBang _, _ + | SynExpr.Sequential _, _ + | SynExpr.Do _, _ + | SynExpr.DoBang _, _ + | SynExpr.IfThenElse _, _ + | SynExpr.TryWith _, _ + | SynExpr.TryFinally _, _ + | SynExpr.ComputationExpr _, _ + | SynExpr.InterpolatedString _, _ -> false + + | _ -> true + + | _ -> true diff --git a/src/Compiler/Service/SynExpr.fsi b/src/Compiler/Service/SynExpr.fsi new file mode 100644 index 00000000000..9e74ce6c1e9 --- /dev/null +++ b/src/Compiler/Service/SynExpr.fsi @@ -0,0 +1,15 @@ +namespace FSharp.Compiler.Syntax + +[] +[] +module public SynExpr = + + /// + /// Returns true if the given expression should be parenthesized in the given context, otherwise false. + /// + /// A function for getting the text of a given source line. + /// The expression's ancestor nodes. + /// The expression to check. + /// True if the given expression should be parenthesized in the given context, otherwise false. + val shouldBeParenthesizedInContext: + getSourceLineStr: (int -> string) -> path: SyntaxVisitorPath -> expr: SynExpr -> bool diff --git a/src/Compiler/Service/SynPat.fs b/src/Compiler/Service/SynPat.fs new file mode 100644 index 00000000000..53212cf17dc --- /dev/null +++ b/src/Compiler/Service/SynPat.fs @@ -0,0 +1,253 @@ +namespace FSharp.Compiler.Syntax + +[] +[] +module SynPat = + let (|Last|) = List.last + + /// Matches if the two values refer to the same object. + [] + let inline (|Is|_|) (inner1: 'a) (inner2: 'a) = + if obj.ReferenceEquals(inner1, inner2) then + ValueSome Is + else + ValueNone + + let (|Ident|) (ident: Ident) = ident.idText + + /// Matches if any pattern in the given list is a SynPat.Typed. + [] + let (|AnyTyped|_|) pats = + if + pats + |> List.exists (function + | SynPat.Typed _ -> true + | _ -> false) + then + ValueSome AnyTyped + else + ValueNone + + /// Matches if any member in the given list is an inherit + /// or implementation of an interface with generic type args. + [] + let (|AnyGenericInheritOrInterfaceImpl|_|) members = + if + members + |> List.exists (function + | SynMemberDefn.ImplicitInherit(inheritType = SynType.App(typeArgs = _ :: _)) + | SynMemberDefn.ImplicitInherit(inheritType = SynType.LongIdentApp(typeArgs = _ :: _)) + | SynMemberDefn.Interface(interfaceType = SynType.App(typeArgs = _ :: _)) + | SynMemberDefn.Interface(interfaceType = SynType.LongIdentApp(typeArgs = _ :: _)) -> true + | _ -> false) + then + ValueSome AnyGenericInheritOrInterfaceImpl + else + ValueNone + + /// Matches the rightmost potentially dangling nested pattern. + let rec (|Rightmost|) pat = + match pat with + | SynPat.Or(rhsPat = Rightmost pat) + | SynPat.ListCons(rhsPat = Rightmost pat) + | SynPat.As(rhsPat = Rightmost pat) + | SynPat.Ands(pats = Last(Rightmost pat)) + | SynPat.Tuple(isStruct = false; elementPats = Last(Rightmost pat)) -> pat + | pat -> pat + + /// Matches if the given pattern is atomic. + [] + let (|Atomic|_|) pat = + match pat with + | SynPat.Named _ + | SynPat.Wild _ + | SynPat.Paren _ + | SynPat.Tuple(isStruct = true) + | SynPat.Record _ + | SynPat.ArrayOrList _ + | SynPat.Const _ + | SynPat.LongIdent(argPats = SynArgPats.Pats []) + | SynPat.Null _ + | SynPat.QuoteExpr _ -> ValueSome Atomic + | _ -> ValueNone + + let shouldBeParenthesizedInContext path pat : bool = + match pat, path with + // Parens are needed in: + // + // let (Pattern …) = … + // let (x: …, y…) = … + // let (x: …), (y: …) = … + // let! (x: …) = … + // and! (x: …) = … + // use! (x: …) = … + // _.member M(x: …) = … + // match … with (x: …) -> … + // match … with (x, y: …) -> … + // function (x: …) -> … + // fun (x, y, …) -> … + // fun (x: …) -> … + // fun (Pattern …) -> … + | SynPat.Typed _, SyntaxNode.SynPat(Rightmost(SynPat.Paren(Is pat, _))) :: SyntaxNode.SynMatchClause _ :: _ + | Rightmost(SynPat.Typed _), SyntaxNode.SynMatchClause _ :: _ + | SynPat.Typed _, SyntaxNode.SynExpr(SynExpr.LetOrUseBang _) :: _ + | SynPat.Typed _, SyntaxNode.SynPat(SynPat.Tuple(isStruct = false)) :: SyntaxNode.SynExpr(SynExpr.LetOrUseBang _) :: _ + | SynPat.Tuple(isStruct = false; elementPats = AnyTyped), SyntaxNode.SynExpr(SynExpr.LetOrUseBang _) :: _ + | SynPat.Typed _, SyntaxNode.SynPat(SynPat.Tuple(isStruct = false)) :: SyntaxNode.SynBinding _ :: _ + | SynPat.Tuple(isStruct = false; elementPats = AnyTyped), SyntaxNode.SynBinding _ :: _ + | SynPat.LongIdent(argPats = SynArgPats.Pats(_ :: _)), SyntaxNode.SynBinding _ :: _ + | SynPat.LongIdent(argPats = SynArgPats.Pats(_ :: _)), SyntaxNode.SynExpr(SynExpr.Lambda _) :: _ + | SynPat.Tuple(isStruct = false), SyntaxNode.SynExpr(SynExpr.Lambda(parsedData = Some _)) :: _ + | SynPat.Typed _, SyntaxNode.SynExpr(SynExpr.Lambda(parsedData = Some _)) :: _ -> true + + // () is parsed as this. + | SynPat.Const(SynConst.Unit, _), _ -> true + + // (()) is required when overriding a generic member + // where unit is the generic type argument: + // + // type C<'T> = abstract M : 'T -> unit + // let _ = { new C with override _.M (()) = () } + | SynPat.Paren(SynPat.Const(SynConst.Unit, _), _), + SyntaxNode.SynPat(SynPat.LongIdent _) :: SyntaxNode.SynBinding _ :: SyntaxNode.SynExpr(SynExpr.ObjExpr( + objType = SynType.App(typeArgs = _ :: _) | SynType.LongIdentApp(typeArgs = _ :: _))) :: _ + | SynPat.Paren(SynPat.Const(SynConst.Unit, _), _), + SyntaxNode.SynPat(SynPat.LongIdent _) :: SyntaxNode.SynBinding _ :: SyntaxNode.SynMemberDefn _ :: SyntaxNode.SynTypeDefn(SynTypeDefn( + typeRepr = SynTypeDefnRepr.ObjectModel(members = AnyGenericInheritOrInterfaceImpl))) :: _ -> true + + // Parens are required around the atomic argument of + // any additional `new` constructor that is not the last. + // + // type T … = + // new (x) = … + // new (x, y) = … + | Atomic, + SyntaxNode.SynPat(SynPat.LongIdent(longDotId = SynLongIdent(id = [ Ident "new" ]))) :: SyntaxNode.SynBinding _ :: SyntaxNode.SynMemberDefn _ :: SyntaxNode.SynTypeDefn(SynTypeDefn( + typeRepr = SynTypeDefnRepr.ObjectModel(members = members))) :: _ -> + let lastNew = + (ValueNone, members) + ||> List.fold (fun lastNew ``member`` -> + match ``member`` with + | SynMemberDefn.Member( + memberDefn = SynBinding(headPat = SynPat.LongIdent(longDotId = SynLongIdent(id = [ Ident "new" ])))) -> + ValueSome ``member`` + | _ -> lastNew) + + match lastNew with + | ValueSome(SynMemberDefn.Member( + memberDefn = SynBinding(headPat = SynPat.LongIdent(argPats = SynArgPats.Pats [ SynPat.Paren(Is pat, _) ])))) -> false + | _ -> true + + // Parens are otherwise never needed in these cases: + // + // let (x: …) = … + // for (…) in (…) do … + // let! (…) = … + // and! (…) = … + // use! (…) = … + // match … with (…) -> … + // function (…) -> … + // function (Pattern …) -> … + // fun (x) -> … + | _, SyntaxNode.SynBinding _ :: _ + | _, SyntaxNode.SynExpr(SynExpr.ForEach _) :: _ + | _, SyntaxNode.SynExpr(SynExpr.LetOrUseBang _) :: _ + | _, SyntaxNode.SynMatchClause _ :: _ + | Atomic, SyntaxNode.SynExpr(SynExpr.Lambda(parsedData = Some _)) :: _ -> false + + // Nested patterns. + | inner, SyntaxNode.SynPat outer :: _ -> + match outer, inner with + // (x :: xs) :: ys + // (x, xs) :: ys + | SynPat.ListCons(lhsPat = SynPat.Paren(pat = Is inner)), SynPat.ListCons _ + | SynPat.ListCons(lhsPat = SynPat.Paren(pat = Is inner)), SynPat.Tuple(isStruct = false) -> true + + // A as (B | C) + // A as (B & C) + // x as (y, z) + // xs as (y :: zs) + | SynPat.As(rhsPat = SynPat.Paren(pat = Is inner)), + (SynPat.Or _ | SynPat.Ands _ | SynPat.Tuple(isStruct = false) | SynPat.ListCons _) -> true + + // (A | B) :: xs + // (A & B) :: xs + // (x as y) :: xs + | SynPat.ListCons _, SynPat.Or _ + | SynPat.ListCons _, SynPat.Ands _ + | SynPat.ListCons _, SynPat.As _ -> true + + // Pattern (x = (…)) + | SynPat.LongIdent(argPats = SynArgPats.NamePatPairs _), _ -> false + + // Pattern (x : int) + // Pattern ([] x) + // Pattern (:? int) + // Pattern (A :: _) + // Pattern (A | B) + // Pattern (A & B) + // Pattern (A as B) + // Pattern (A, B) + // Pattern1 (Pattern2 (x = A)) + // Pattern1 (Pattern2 x y) + | SynPat.LongIdent _, SynPat.Typed _ + | SynPat.LongIdent _, SynPat.Attrib _ + | SynPat.LongIdent _, SynPat.IsInst _ + | SynPat.LongIdent _, SynPat.ListCons _ + | SynPat.LongIdent _, SynPat.Or _ + | SynPat.LongIdent _, SynPat.Ands _ + | SynPat.LongIdent _, SynPat.As _ + | SynPat.LongIdent _, SynPat.Tuple(isStruct = false) + | SynPat.LongIdent _, SynPat.LongIdent(argPats = SynArgPats.NamePatPairs _) + | SynPat.LongIdent _, SynPat.LongIdent(argPats = SynArgPats.Pats(_ :: _)) + + // A | (B as C) + // A & (B as C) + // A, (B as C) + | SynPat.Or _, SynPat.As _ + | SynPat.Ands _, SynPat.As _ + | SynPat.Tuple _, SynPat.As _ + + // x, (y, z) + // x & (y, z) + // (x, y) & z + | SynPat.Tuple _, SynPat.Tuple(isStruct = false) + | SynPat.Ands _, SynPat.Tuple(isStruct = false) + + // A, (B | C) + // A & (B | C) + | SynPat.Tuple _, SynPat.Or _ + | SynPat.Ands _, SynPat.Or _ -> true + + // (x : int) & y + // x & (y : int) & z + | SynPat.Ands(Last(SynPat.Paren(pat = Is inner)), _), SynPat.Typed _ -> false + | SynPat.Ands _, SynPat.Typed _ -> true + + | _, SynPat.Const _ + | _, SynPat.Wild _ + | _, SynPat.Named _ + | _, SynPat.Typed _ + | _, SynPat.LongIdent(argPats = SynArgPats.Pats []) + | _, SynPat.Tuple(isStruct = true) + | _, SynPat.Paren _ + | _, SynPat.ArrayOrList _ + | _, SynPat.Record _ + | _, SynPat.Null _ + | _, SynPat.OptionalVal _ + | _, SynPat.IsInst _ + | _, SynPat.QuoteExpr _ + + | SynPat.Or _, _ + | SynPat.ListCons _, _ + | SynPat.Ands _, _ + | SynPat.As _, _ + | SynPat.LongIdent _, _ + | SynPat.Tuple _, _ + | SynPat.Paren _, _ + | SynPat.ArrayOrList _, _ + | SynPat.Record _, _ -> false + + | _ -> true + + | _ -> true diff --git a/src/Compiler/Service/SynPat.fsi b/src/Compiler/Service/SynPat.fsi new file mode 100644 index 00000000000..77bcd9c600c --- /dev/null +++ b/src/Compiler/Service/SynPat.fsi @@ -0,0 +1,13 @@ +namespace FSharp.Compiler.Syntax + +[] +[] +module public SynPat = + + /// + /// Returns true if the given pattern should be parenthesized in the given context, otherwise false. + /// + /// The pattern's ancestor nodes. + /// The pattern to check. + /// True if the given pattern should be parenthesized in the given context, otherwise false. + val shouldBeParenthesizedInContext: path: SyntaxVisitorPath -> pat: SynPat -> bool diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs new file mode 100644 index 00000000000..298c0e6b627 --- /dev/null +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -0,0 +1,2071 @@ +namespace FSharp.Compiler.CodeAnalysis.TransparentCompiler + +open System +open System.Collections.Generic +open System.Runtime.CompilerServices +open System.Diagnostics +open System.IO + +open Internal.Utilities.Collections +open Internal.Utilities.Library + +open FSharp.Compiler +open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.ILBinaryReader +open FSharp.Compiler.BuildGraph +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.CompilerConfig +open FSharp.Compiler.CompilerImports +open FSharp.Compiler.CompilerOptions +open FSharp.Compiler.CheckBasics +open FSharp.Compiler.DependencyManager +open FSharp.Compiler.Diagnostics +open FSharp.Compiler.DiagnosticsLogger +open FSharp.Compiler.IO +open FSharp.Compiler.ScriptClosure +open FSharp.Compiler.Symbols +open FSharp.Compiler.TcGlobals +open FSharp.Compiler.Text +open FSharp.Compiler.Text.Range +open FSharp.Compiler.Xml +open System.Threading.Tasks +open FSharp.Compiler.ParseAndCheckInputs +open FSharp.Compiler.GraphChecking +open FSharp.Compiler.Syntax +open FSharp.Compiler.CompilerDiagnostics +open FSharp.Compiler.NameResolution +open Internal.Utilities.Library.Extras +open FSharp.Compiler.TypedTree +open FSharp.Compiler.CheckDeclarations +open FSharp.Compiler.EditorServices +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.CreateILModule +open FSharp.Compiler.TypedTreeOps +open System.Threading +open Internal.Utilities.Hashing + +open FSharp.Compiler.CodeAnalysis.ProjectSnapshot + +/// Accumulated results of type checking. The minimum amount of state in order to continue type-checking following files. +[] +type internal TcInfo = + { + tcState: TcState + tcEnvAtEndOfFile: TcEnv + + /// Disambiguation table for module names + moduleNamesDict: ModuleNamesDict + + topAttribs: TopAttribs option + + latestCcuSigForFile: ModuleOrNamespaceType option + + /// Accumulated diagnostics, last file first + tcDiagnosticsRev: (PhasedDiagnostic * FSharpDiagnosticSeverity)[] list + + tcDependencyFiles: string list + + sigNameOpt: (string * QualifiedNameOfFile) option + + graphNode: NodeToTypeCheck option + + stateContainsNodes: Set + + sink: TcResultsSinkImpl list + } + + member x.TcDiagnostics = Array.concat (List.rev x.tcDiagnosticsRev) + +[] +type internal TcIntermediate = + { + finisher: Finisher + //tcEnvAtEndOfFile: TcEnv + + /// Disambiguation table for module names + moduleNamesDict: ModuleNamesDict + + /// Accumulated diagnostics, last file first + tcDiagnosticsRev: (PhasedDiagnostic * FSharpDiagnosticSeverity)[] list + + tcDependencyFiles: string list + + sink: TcResultsSinkImpl + } + +/// Things we need to start parsing and checking files for a given project snapshot +type internal BootstrapInfo = + { + // Each instance gets an Id on creation, unfortunately partial type check results using different instances are not compatible + // So if this needs to be recreated for whatever reason then we need to re type check all files + Id: int + + AssemblyName: string + OutFile: string + TcConfig: TcConfig + TcImports: TcImports + TcGlobals: TcGlobals + InitialTcInfo: TcInfo + + // TODO: Figure out how these work and if they need to be added to the snapshot... + LoadedSources: (range * FSharpFileSnapshot) list + + // TODO: Might be a bit more complicated if we want to support adding files to the project via OtherOptions + // ExtraSourceFilesAfter: FSharpFileSnapshot list + + LoadClosure: LoadClosure option + LastFileName: string + } + +type internal TcIntermediateResult = TcInfo * TcResultsSinkImpl * CheckedImplFile option * string + +[] +type internal DependencyGraphType = + /// A dependency graph for a single file - it will be missing files which this file does not depend on + | File + /// A dependency graph for a project - it will contain all files in the project + | Project + +[] +type internal Extensions = + [] + static member Key<'T when 'T :> IFileSnapshot>(fileSnapshots: 'T list, ?extraKeyFlag) = + + { new ICacheKey<_, _> with + member _.GetLabel() = + let lastFile = + fileSnapshots + |> List.tryLast + |> Option.map (fun f -> f.FileName |> shortPath) + |> Option.defaultValue "[no file]" + + $"%d{fileSnapshots.Length} files ending with {lastFile}" + + member _.GetKey() = + Md5Hasher.empty + |> Md5Hasher.addStrings (fileSnapshots |> Seq.map (fun f -> f.FileName)) + |> pair extraKeyFlag + + member _.GetVersion() = + Md5Hasher.empty + |> Md5Hasher.addBytes' (fileSnapshots |> Seq.map (fun f -> f.Version)) + |> Md5Hasher.toString + } + +[] +module private TypeCheckingGraphProcessing = + open FSharp.Compiler.GraphChecking.GraphProcessing + + // TODO Do we need to suppress some error logging if we + // TODO apply the same partial results multiple times? + // TODO Maybe we can enable logging only for the final fold + /// + /// Combine type-checking results of dependencies needed to type-check a 'higher' node in the graph + /// + /// Initial state + /// Direct dependencies of a node + /// Transitive dependencies of a node + /// A way to fold a single result into existing state + let private combineResults + (emptyState: TcInfo) + (deps: ProcessedNode> array) + (transitiveDeps: ProcessedNode> array) + (folder: TcInfo -> Finisher -> TcInfo) + : TcInfo = + match deps with + | [||] -> emptyState + | _ -> + // Instead of starting with empty state, + // reuse state produced by the dependency with the biggest number of transitive dependencies. + // This is to reduce the number of folds required to achieve the final state. + let biggestDependency = + let sizeMetric (node: ProcessedNode<_, _>) = node.Info.TransitiveDeps.Length + deps |> Array.maxBy sizeMetric + + let firstState = biggestDependency.Result |> fst + + // Find items not already included in the state. + let itemsPresent = + set + [| + yield! biggestDependency.Info.TransitiveDeps + yield biggestDependency.Info.Item + |] + + let resultsToAdd = + transitiveDeps + |> Array.filter (fun dep -> itemsPresent.Contains dep.Info.Item = false) + |> Array.distinctBy (fun dep -> dep.Info.Item) + |> Array.sortWith (fun a b -> + // We preserve the order in which items are folded to the state. + match a.Info.Item, b.Info.Item with + | NodeToTypeCheck.PhysicalFile aIdx, NodeToTypeCheck.PhysicalFile bIdx + | NodeToTypeCheck.ArtificialImplFile aIdx, NodeToTypeCheck.ArtificialImplFile bIdx -> aIdx.CompareTo bIdx + | NodeToTypeCheck.PhysicalFile _, NodeToTypeCheck.ArtificialImplFile _ -> -1 + | NodeToTypeCheck.ArtificialImplFile _, NodeToTypeCheck.PhysicalFile _ -> 1) + |> Array.map (fun dep -> dep.Result |> snd) + + // Fold results not already included and produce the final state + let state = Array.fold folder firstState resultsToAdd + state + + /// + /// Process a graph of items. + /// A version of 'GraphProcessing.processGraph' with a signature specific to type-checking. + /// + let processTypeCheckingGraph + (graph: Graph) + (work: NodeToTypeCheck -> TcInfo -> Async>) + (emptyState: TcInfo) + : Async<(int * PartialResult) list * TcInfo> = + async { + + let workWrapper + (getProcessedNode: + NodeToTypeCheck -> ProcessedNode>) + (node: NodeInfo) + : Async> = + async { + let folder (state: TcInfo) (Finisher(finisher = finisher)) : TcInfo = finisher state |> snd + let deps = node.Deps |> Array.except [| node.Item |] |> Array.map getProcessedNode + + let transitiveDeps = + node.TransitiveDeps + |> Array.except [| node.Item |] + |> Array.map getProcessedNode + + let inputState = combineResults emptyState deps transitiveDeps folder + + let! singleRes = work node.Item inputState + let state = folder inputState singleRes + return state, singleRes + } + + let! results = processGraphAsync graph workWrapper + + let finalFileResults, state = + (([], emptyState), + results + |> Array.choose (fun (item, res) -> + match item with + | NodeToTypeCheck.ArtificialImplFile _ -> None + | NodeToTypeCheck.PhysicalFile file -> Some(file, res))) + ||> Array.fold (fun (fileResults, state) (item, (_, Finisher(finisher = finisher))) -> + let fileResult, state = finisher state + (item, fileResult) :: fileResults, state) + + return finalFileResults, state + } + +type internal CompilerCaches(sizeFactor: int) = + + let sf = sizeFactor + + member _.SizeFactor = sf + + member val ParseFile = AsyncMemoize(keepStrongly = 50 * sf, keepWeakly = 20 * sf, name = "ParseFile") + + member val ParseAndCheckFileInProject = AsyncMemoize(sf, 2 * sf, name = "ParseAndCheckFileInProject") + + member val ParseAndCheckAllFilesInProject = AsyncMemoizeDisabled(sf, 2 * sf, name = "ParseAndCheckFullProject") + + member val ParseAndCheckProject = AsyncMemoize(sf, 2 * sf, name = "ParseAndCheckProject") + + member val FrameworkImports = AsyncMemoize(sf, 2 * sf, name = "FrameworkImports") + + member val BootstrapInfoStatic = AsyncMemoize(sf, 2 * sf, name = "BootstrapInfoStatic") + + member val BootstrapInfo = AsyncMemoize(sf, 2 * sf, name = "BootstrapInfo") + + member val TcLastFile = AsyncMemoizeDisabled(sf, 2 * sf, name = "TcLastFile") + + member val TcIntermediate = AsyncMemoize(20 * sf, 20 * sf, name = "TcIntermediate") + + member val DependencyGraph = AsyncMemoize(sf, 2 * sf, name = "DependencyGraph") + + member val ProjectExtras = AsyncMemoizeDisabled(sf, 2 * sf, name = "ProjectExtras") + + member val AssemblyData = AsyncMemoize(sf, 2 * sf, name = "AssemblyData") + + member val SemanticClassification = AsyncMemoize(sf, 2 * sf, name = "SemanticClassification") + + member val ItemKeyStore = AsyncMemoize(sf, 2 * sf, name = "ItemKeyStore") + + member this.Clear(projects: Set) = + let shouldClear project = projects |> Set.contains project + + this.ParseFile.Clear(fst >> shouldClear) + this.ParseAndCheckFileInProject.Clear(snd >> shouldClear) + this.ParseAndCheckProject.Clear(shouldClear) + this.BootstrapInfoStatic.Clear(shouldClear) + this.BootstrapInfo.Clear(shouldClear) + this.TcIntermediate.Clear(snd >> shouldClear) + this.AssemblyData.Clear(shouldClear) + this.SemanticClassification.Clear(snd >> shouldClear) + this.ItemKeyStore.Clear(snd >> shouldClear) + +type internal TransparentCompiler + ( + legacyReferenceResolver, + projectCacheSize, + keepAssemblyContents, + keepAllBackgroundResolutions, + tryGetMetadataSnapshot, + suggestNamesForErrors, + keepAllBackgroundSymbolUses, + enableBackgroundItemKeyStoreAndSemanticClassification, + enablePartialTypeChecking, + parallelReferenceResolution, + captureIdentifiersWhenParsing, + getSource: (string -> Async) option, + useChangeNotifications, + useSyntaxTreeCache + ) as self = + + // Is having just one of these ok? + let lexResourceManager = Lexhelp.LexResourceManager() + + // Mutable so we can easily clear them by creating a new instance + let mutable caches = CompilerCaches(100) + + // TODO: do we need this? + //let maxTypeCheckingParallelism = max 1 (Environment.ProcessorCount / 2) + //let maxParallelismSemaphore = new SemaphoreSlim(maxTypeCheckingParallelism) + + // We currently share one global dependency provider for all scripts for the FSharpChecker. + // For projects, one is used per project. + // + // Sharing one for all scripts is necessary for good performance from GetProjectOptionsFromScript, + // which requires a dependency provider to process through the project options prior to working out + // if the cached incremental builder can be used for the project. + let dependencyProviderForScripts = new DependencyProvider() + + // Legacy events, they're used in tests... eventually they should go away + let beforeFileChecked = Event() + let fileParsed = Event() + let fileChecked = Event() + let projectChecked = Event() + + // use this to process not-yet-implemented tasks + let backgroundCompiler = + BackgroundCompiler( + legacyReferenceResolver, + projectCacheSize, + keepAssemblyContents, + keepAllBackgroundResolutions, + tryGetMetadataSnapshot, + suggestNamesForErrors, + keepAllBackgroundSymbolUses, + enableBackgroundItemKeyStoreAndSemanticClassification, + enablePartialTypeChecking, + parallelReferenceResolution, + captureIdentifiersWhenParsing, + getSource, + useChangeNotifications, + useSyntaxTreeCache + ) + :> IBackgroundCompiler + + let ComputeFrameworkImports (tcConfig: TcConfig) frameworkDLLs nonFrameworkResolutions = + let frameworkDLLsKey = + frameworkDLLs + |> List.map (fun ar -> ar.resolvedPath) // The cache key. Just the minimal data. + |> List.sort // Sort to promote cache hits. + + // The data elements in this key are very important. There should be nothing else in the TcConfig that logically affects + // the import of a set of framework DLLs into F# CCUs. That is, the F# CCUs that result from a set of DLLs (including + // FSharp.Core.dll and mscorlib.dll) must be logically invariant of all the other compiler configuration parameters. + let key = + FrameworkImportsCacheKey( + frameworkDLLsKey, + tcConfig.primaryAssembly.Name, + tcConfig.GetTargetFrameworkDirectories(), + tcConfig.fsharpBinariesDir, + tcConfig.langVersion.SpecifiedVersion + ) + + caches.FrameworkImports.Get( + key, + node { + use _ = Activity.start "ComputeFrameworkImports" [] + let tcConfigP = TcConfigProvider.Constant tcConfig + + return! TcImports.BuildFrameworkTcImports(tcConfigP, frameworkDLLs, nonFrameworkResolutions) + } + ) + + // Link all the assemblies together and produce the input typecheck accumulator + let CombineImportedAssembliesTask + ( + assemblyName, + tcConfig: TcConfig, + tcConfigP, + tcGlobals, + frameworkTcImports, + nonFrameworkResolutions, + unresolvedReferences, + dependencyProvider, + loadClosureOpt: LoadClosure option, + basicDependencies, + importsInvalidatedByTypeProvider: Event + ) = + + node { + let diagnosticsLogger = + CompilationDiagnosticLogger("CombineImportedAssembliesTask", tcConfig.diagnosticsOptions) + + use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter) + + let! tcImports = + node { + try + let! tcImports = + TcImports.BuildNonFrameworkTcImports( + tcConfigP, + frameworkTcImports, + nonFrameworkResolutions, + unresolvedReferences, + dependencyProvider + ) +#if !NO_TYPEPROVIDERS + // TODO: review and handle the event + tcImports.GetCcusExcludingBase() + |> Seq.iter (fun ccu -> + // When a CCU reports an invalidation, merge them together and just report a + // general "imports invalidated". This triggers a rebuild. + // + // We are explicit about what the handler closure captures to help reason about the + // lifetime of captured objects, especially in case the type provider instance gets leaked + // or keeps itself alive mistakenly, e.g. via some global state in the type provider instance. + // + // The handler only captures + // 1. a weak reference to the importsInvalidated event. + // + // The IncrementalBuilder holds the strong reference the importsInvalidated event. + // + // In the invalidation handler we use a weak reference to allow the IncrementalBuilder to + // be collected if, for some reason, a TP instance is not disposed or not GC'd. + let capturedImportsInvalidated = WeakReference<_>(importsInvalidatedByTypeProvider) + + ccu.Deref.InvalidateEvent.Add(fun _ -> + match capturedImportsInvalidated.TryGetTarget() with + | true, tg -> tg.Trigger() + | _ -> ())) +#endif +#if NO_TYPEPROVIDERS + ignore importsInvalidatedByTypeProvider +#endif + return tcImports + with + | :? OperationCanceledException -> + // if it's been canceled then it shouldn't be needed anymore + return frameworkTcImports + | exn -> + Debug.Assert(false, sprintf "Could not BuildAllReferencedDllTcImports %A" exn) + diagnosticsLogger.Warning exn + return frameworkTcImports + } + + let tcInitial, openDecls0 = + GetInitialTcEnv(assemblyName, rangeStartup, tcConfig, tcImports, tcGlobals) + + let tcState = + GetInitialTcState(rangeStartup, assemblyName, tcConfig, tcGlobals, tcImports, tcInitial, openDecls0) + + let loadClosureErrors = + [ + match loadClosureOpt with + | None -> () + | Some loadClosure -> + for inp in loadClosure.Inputs do + yield! inp.MetaCommandDiagnostics + ] + + let initialErrors = + Array.append (Array.ofList loadClosureErrors) (diagnosticsLogger.GetDiagnostics()) + + let tcInfo = + { + tcState = tcState + tcEnvAtEndOfFile = tcInitial + topAttribs = None + latestCcuSigForFile = None + tcDiagnosticsRev = [ initialErrors ] + moduleNamesDict = Map.empty + tcDependencyFiles = basicDependencies + sigNameOpt = None + graphNode = None + stateContainsNodes = Set.empty + sink = [] + } + + return tcImports, tcInfo + } + + let getProjectReferences (project: ProjectSnapshotBase<_>) userOpName = + [ + for r in project.ReferencedProjects do + + match r with + | FSharpReferencedProjectSnapshot.FSharpReference(nm, projectSnapshot) -> + // Don't use cross-project references for FSharp.Core, since various bits of code + // require a concrete FSharp.Core to exist on-disk. The only solutions that have + // these cross-project references to FSharp.Core are VisualFSharp.sln and FSharp.sln. The ramification + // of this is that you need to build FSharp.Core to get intellisense in those projects. + + if + (try + Path.GetFileNameWithoutExtension(nm) + with _ -> + "") + <> GetFSharpCoreLibraryName() + then + { new IProjectReference with + member x.EvaluateRawContents() = + node { + Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "GetAssemblyData", nm) + + return! + self.GetAssemblyData( + projectSnapshot.ProjectSnapshot, + nm, + userOpName + ".CheckReferencedProject(" + nm + ")" + ) + } + + member x.TryGetLogicalTimeStamp(cache) = + // TODO: + None + + member x.FileName = nm + } + ] + + let ComputeTcConfigBuilder (projectSnapshot: ProjectSnapshotBase<_>) = + + let useSimpleResolutionSwitch = "--simpleresolution" + let commandLineArgs = projectSnapshot.CommandLineOptions + let defaultFSharpBinariesDir = FSharpCheckerResultsSettings.defaultFSharpBinariesDir + let useScriptResolutionRules = projectSnapshot.UseScriptResolutionRules + + let projectReferences = + getProjectReferences projectSnapshot "ComputeTcConfigBuilder" + + // TODO: script support + let loadClosureOpt: LoadClosure option = None + + let getSwitchValue (switchString: string) = + match commandLineArgs |> List.tryFindIndex (fun s -> s.StartsWithOrdinal switchString) with + | Some idx -> Some(commandLineArgs[idx].Substring(switchString.Length)) + | _ -> None + + let sdkDirOverride = + match loadClosureOpt with + | None -> None + | Some loadClosure -> loadClosure.SdkDirOverride + + // see also fsc.fs: runFromCommandLineToImportingAssemblies(), as there are many similarities to where the PS creates a tcConfigB + let tcConfigB = + TcConfigBuilder.CreateNew( + legacyReferenceResolver, + defaultFSharpBinariesDir, + implicitIncludeDir = projectSnapshot.ProjectDirectory, + reduceMemoryUsage = ReduceMemoryFlag.Yes, + isInteractive = useScriptResolutionRules, + isInvalidationSupported = true, + defaultCopyFSharpCore = CopyFSharpCoreFlag.No, + tryGetMetadataSnapshot = tryGetMetadataSnapshot, + sdkDirOverride = sdkDirOverride, + rangeForErrors = range0 + ) + + tcConfigB.primaryAssembly <- + match loadClosureOpt with + | None -> PrimaryAssembly.Mscorlib + | Some loadClosure -> + if loadClosure.UseDesktopFramework then + PrimaryAssembly.Mscorlib + else + PrimaryAssembly.System_Runtime + + tcConfigB.resolutionEnvironment <- (LegacyResolutionEnvironment.EditingOrCompilation true) + + tcConfigB.conditionalDefines <- + let define = + if useScriptResolutionRules then + "INTERACTIVE" + else + "COMPILED" + + define :: tcConfigB.conditionalDefines + + tcConfigB.projectReferences <- projectReferences + + tcConfigB.useSimpleResolution <- (getSwitchValue useSimpleResolutionSwitch) |> Option.isSome + + // Apply command-line arguments and collect more source files if they are in the arguments + let sourceFilesNew = + ApplyCommandLineArgs(tcConfigB, projectSnapshot.SourceFileNames, commandLineArgs) + + // Never open PDB files for the language service, even if --standalone is specified + tcConfigB.openDebugInformationForLaterStaticLinking <- false + + tcConfigB.xmlDocInfoLoader <- + { new IXmlDocumentationInfoLoader with + /// Try to load xml documentation associated with an assembly by the same file path with the extension ".xml". + member _.TryLoad(assemblyFileName) = + let xmlFileName = Path.ChangeExtension(assemblyFileName, ".xml") + + // REVIEW: File IO - Will eventually need to change this to use a file system interface of some sort. + XmlDocumentationInfo.TryCreateFromFile(xmlFileName) + } + |> Some + + tcConfigB.parallelReferenceResolution <- parallelReferenceResolution + tcConfigB.captureIdentifiersWhenParsing <- captureIdentifiersWhenParsing + + tcConfigB, sourceFilesNew, loadClosureOpt + + let mutable BootstrapInfoIdCounter = 0 + + /// Bootstrap info that does not depend source files + let ComputeBootstrapInfoStatic (projectSnapshot: ProjectCore, tcConfig: TcConfig, assemblyName: string, loadClosureOpt) = + + caches.BootstrapInfoStatic.Get( + projectSnapshot.CacheKeyWith("BootstrapInfoStatic", assemblyName), + node { + use _ = + Activity.start + "ComputeBootstrapInfoStatic" + [| + Activity.Tags.project, projectSnapshot.ProjectFileName |> Path.GetFileName + "references", projectSnapshot.ReferencedProjects.Length.ToString() + |] + + // Resolve assemblies and create the framework TcImports. This caches a level of "system" references. No type providers are + // included in these references. + + let frameworkDLLs, nonFrameworkResolutions, unresolvedReferences = + TcAssemblyResolutions.SplitNonFoundationalResolutions(tcConfig) + + // Prepare the frameworkTcImportsCache + let! tcGlobals, frameworkTcImports = ComputeFrameworkImports tcConfig frameworkDLLs nonFrameworkResolutions + + // Note we are not calling diagnosticsLogger.GetDiagnostics() anywhere for this task. + // This is ok because not much can actually go wrong here. + let diagnosticsLogger = + CompilationDiagnosticLogger("nonFrameworkAssemblyInputs", tcConfig.diagnosticsOptions) + + use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter) + + let tcConfigP = TcConfigProvider.Constant tcConfig + + let importsInvalidatedByTypeProvider = Event() + + let basicDependencies = + [ + for UnresolvedAssemblyReference(referenceText, _) in unresolvedReferences do + // Exclude things that are definitely not a file name + if not (FileSystem.IsInvalidPathShim referenceText) then + let file = + if FileSystem.IsPathRootedShim referenceText then + referenceText + else + Path.Combine(projectSnapshot.ProjectDirectory, referenceText) + + yield file + + for r in nonFrameworkResolutions do + yield r.resolvedPath + ] + + // For scripts, the dependency provider is already available. + // For projects create a fresh one for the project. + let dependencyProvider = + if projectSnapshot.UseScriptResolutionRules then + dependencyProviderForScripts + else + new DependencyProvider() + + let! tcImports, initialTcInfo = + CombineImportedAssembliesTask( + assemblyName, + tcConfig, + tcConfigP, + tcGlobals, + frameworkTcImports, + nonFrameworkResolutions, + unresolvedReferences, + dependencyProvider, + loadClosureOpt, + basicDependencies, + importsInvalidatedByTypeProvider + ) + + let bootstrapId = Interlocked.Increment &BootstrapInfoIdCounter + + return bootstrapId, tcImports, tcGlobals, initialTcInfo, importsInvalidatedByTypeProvider + } + ) + + let computeBootstrapInfoInner (projectSnapshot: ProjectSnapshot) = + node { + + let tcConfigB, sourceFiles, loadClosureOpt = ComputeTcConfigBuilder projectSnapshot + + // If this is a builder for a script, re-apply the settings inferred from the + // script and its load closure to the configuration. + // + // NOTE: it would probably be cleaner and more accurate to re-run the load closure at this point. + let setupConfigFromLoadClosure () = + match loadClosureOpt with + | Some loadClosure -> + let dllReferences = + [ + for reference in tcConfigB.referencedDLLs do + // If there's (one or more) resolutions of closure references then yield them all + match + loadClosure.References + |> List.tryFind (fun (resolved, _) -> resolved = reference.Text) + with + | Some(resolved, closureReferences) -> + for closureReference in closureReferences do + yield AssemblyReference(closureReference.originalReference.Range, resolved, None) + | None -> yield reference + ] + + tcConfigB.referencedDLLs <- [] + + tcConfigB.primaryAssembly <- + (if loadClosure.UseDesktopFramework then + PrimaryAssembly.Mscorlib + else + PrimaryAssembly.System_Runtime) + // Add one by one to remove duplicates + dllReferences + |> List.iter (fun dllReference -> tcConfigB.AddReferencedAssemblyByPath(dllReference.Range, dllReference.Text)) + + tcConfigB.knownUnresolvedReferences <- loadClosure.UnresolvedReferences + | None -> () + + setupConfigFromLoadClosure () + + let tcConfig = TcConfig.Create(tcConfigB, validate = true) + let outFile, _, assemblyName = tcConfigB.DecideNames sourceFiles + + let! bootstrapId, tcImports, tcGlobals, initialTcInfo, _importsInvalidatedByTypeProvider = + ComputeBootstrapInfoStatic(projectSnapshot.ProjectCore, tcConfig, assemblyName, loadClosureOpt) + + // Check for the existence of loaded sources and prepend them to the sources list if present. + let loadedSources = + tcConfig.GetAvailableLoadedSources() + |> List.map (fun (m, fileName) -> m, FSharpFileSnapshot.CreateFromFileSystem(fileName)) + + return + Some + { + Id = bootstrapId + AssemblyName = assemblyName + OutFile = outFile + TcConfig = tcConfig + TcImports = tcImports + TcGlobals = tcGlobals + InitialTcInfo = initialTcInfo + LoadedSources = loadedSources + LoadClosure = loadClosureOpt + LastFileName = sourceFiles |> List.last + //ImportsInvalidatedByTypeProvider = importsInvalidatedByTypeProvider + } + } + + let ComputeBootstrapInfo (projectSnapshot: ProjectSnapshot) = + + caches.BootstrapInfo.Get( + projectSnapshot.NoFileVersionsKey, + node { + use _ = + Activity.start "ComputeBootstrapInfo" [| Activity.Tags.project, projectSnapshot.ProjectFileName |> Path.GetFileName |] + + // Trap and report diagnostics from creation. + let delayedLogger = CapturingDiagnosticsLogger("IncrementalBuilderCreation") + use _ = new CompilationGlobalsScope(delayedLogger, BuildPhase.Parameter) + + let! bootstrapInfoOpt = + node { + try + return! computeBootstrapInfoInner projectSnapshot + with exn -> + errorRecoveryNoRange exn + return None + } + + let diagnostics = + match bootstrapInfoOpt with + | Some bootstrapInfo -> + let diagnosticsOptions = bootstrapInfo.TcConfig.diagnosticsOptions + + let diagnosticsLogger = + CompilationDiagnosticLogger("IncrementalBuilderCreation", diagnosticsOptions) + + delayedLogger.CommitDelayedDiagnostics diagnosticsLogger + diagnosticsLogger.GetDiagnostics() + | _ -> Array.ofList delayedLogger.Diagnostics + |> Array.map (fun (diagnostic, severity) -> + let flatErrors = + bootstrapInfoOpt + |> Option.map (fun bootstrapInfo -> bootstrapInfo.TcConfig.flatErrors) + |> Option.defaultValue false // TODO: do we need to figure this out? + + FSharpDiagnostic.CreateFromException(diagnostic, severity, range.Zero, suggestNamesForErrors, flatErrors, None)) + + return bootstrapInfoOpt, diagnostics + } + ) + + // TODO: Not sure if we should cache this. For VS probably not. Maybe it can be configurable by FCS user. + let LoadSource (file: FSharpFileSnapshot) isExe isLastCompiland = + node { + let! source = file.GetSource() |> NodeCode.AwaitTask + + return + FSharpFileSnapshotWithSource( + FileName = file.FileName, + Source = source, + SourceHash = source.GetChecksum(), + IsLastCompiland = isLastCompiland, + IsExe = isExe + ) + } + + let LoadSources (bootstrapInfo: BootstrapInfo) (projectSnapshot: ProjectSnapshot) = + node { + let isExe = bootstrapInfo.TcConfig.target.IsExe + + let! sources = + projectSnapshot.SourceFiles + |> Seq.map (fun f -> LoadSource f isExe (f.FileName = bootstrapInfo.LastFileName)) + |> NodeCode.Parallel + + return ProjectSnapshotWithSources(projectSnapshot.ProjectCore, sources |> Array.toList) + + } + + let ComputeParseFile (projectSnapshot: ProjectSnapshotBase<_>) (tcConfig: TcConfig) (file: FSharpFileSnapshotWithSource) = + + let key = + { new ICacheKey<_, _> with + member _.GetLabel() = file.FileName |> shortPath + + member _.GetKey() = + projectSnapshot.ProjectCore.Identifier, file.FileName + + member _.GetVersion() = + projectSnapshot.ParsingVersion, + file.StringVersion, + // TODO: is there a situation where this is not enough and we need to have them separate? + file.IsLastCompiland && file.IsExe + } + + caches.ParseFile.Get( + key, + node { + use _ = + Activity.start + "ComputeParseFile" + [| + Activity.Tags.fileName, file.FileName |> shortPath + Activity.Tags.version, file.StringVersion + |] + + let diagnosticsLogger = + CompilationDiagnosticLogger("Parse", tcConfig.diagnosticsOptions) + // Return the disposable object that cleans up + use _holder = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parse) + + let flags = file.IsLastCompiland, file.IsExe + let fileName = file.FileName + let sourceText = file.Source + + let input = + ParseOneInputSourceText(tcConfig, lexResourceManager, fileName, flags, diagnosticsLogger, sourceText) + + // TODO: Hashing of syntax tree + let inputHash = file.Version + + fileParsed.Trigger(fileName, Unchecked.defaultof<_>) + + return FSharpParsedFile(fileName, inputHash, sourceText, input, diagnosticsLogger.GetDiagnostics()) + } + ) + + // In case we don't want to use any parallel processing + let mkLinearGraph count : Graph = + seq { + 0, [||] + + yield! + [ 0 .. count - 1 ] + |> Seq.rev + |> Seq.pairwise + |> Seq.map (fun (a, b) -> a, [| b |]) + } + |> Graph.make + + let computeDependencyGraph (tcConfig: TcConfig) parsedInputs (processGraph: Graph -> Graph) = + node { + let sourceFiles: FileInProject array = + parsedInputs + |> Seq.toArray + |> Array.mapi (fun idx (input: ParsedInput) -> + { + Idx = idx + FileName = input.FileName + ParsedInput = input + }) + + use _ = + Activity.start "ComputeDependencyGraph" [| Activity.Tags.fileName, (sourceFiles |> Array.last).FileName |] + + let filePairs = FilePairMap(sourceFiles) + + // TODO: we will probably want to cache and re-use larger graphs if available + + let graph = + if tcConfig.compilingFSharpCore then + mkLinearGraph sourceFiles.Length + else + DependencyResolution.mkGraph filePairs sourceFiles |> fst |> processGraph + + let nodeGraph = TransformDependencyGraph(graph, filePairs) + + let fileNames = + parsedInputs + |> Seq.mapi (fun idx input -> idx, Path.GetFileName input.FileName) + |> Map.ofSeq + + let debugGraph = + nodeGraph + |> Graph.map (function + | NodeToTypeCheck.PhysicalFile i -> i, $"[{i}] {fileNames[i]}" + | NodeToTypeCheck.ArtificialImplFile i -> -(i + 1), $"AIF [{i}] : {fileNames[i]}") + |> Graph.serialiseToMermaid + + //Trace.TraceInformation("\n" + debugGraph) + + if Activity.Current <> null then + Activity.Current.AddTag("graph", debugGraph) |> ignore + + return nodeGraph, graph + } + + let removeImplFilesThatHaveSignatures (projectSnapshot: ProjectSnapshot) (graph: Graph) = + + let removeIndexes = + projectSnapshot.SourceFileNames + |> Seq.mapi pair + |> Seq.groupBy ( + snd + >> (fun fileName -> + if fileName.EndsWith(".fsi") then + fileName.Substring(0, fileName.Length - 1) + else + fileName) + ) + |> Seq.map (snd >> (Seq.toList)) + |> Seq.choose (function + | [ idx1, _; idx2, _ ] -> max idx1 idx2 |> Some + | _ -> None) + |> Set + + graph + |> Seq.filter (fun x -> not (removeIndexes.Contains x.Key)) + |> Seq.map (fun x -> x.Key, x.Value |> Array.filter (fun node -> not (removeIndexes.Contains node))) + |> Graph.make + + let removeImplFilesThatHaveSignaturesExceptLastOne (projectSnapshot: ProjectSnapshotBase<_>) (graph: Graph) = + + let removeIndexes = + projectSnapshot.SourceFileNames + |> Seq.mapi pair + |> Seq.groupBy ( + snd + >> (fun fileName -> + if fileName.EndsWith(".fsi") then + fileName.Substring(0, fileName.Length - 1) + else + fileName) + ) + |> Seq.map (snd >> (Seq.toList)) + |> Seq.choose (function + | [ idx1, _; idx2, _ ] -> max idx1 idx2 |> Some + | _ -> None) + |> Set + // Don't remove the last file + |> Set.remove (projectSnapshot.SourceFiles.Length - 1) + + graph + |> Seq.filter (fun x -> not (removeIndexes.Contains x.Key)) + |> Seq.map (fun x -> x.Key, x.Value |> Array.filter (fun node -> not (removeIndexes.Contains node))) + |> Graph.make + + let ComputeDependencyGraphForFile (tcConfig: TcConfig) (priorSnapshot: ProjectSnapshotBase) = + let key = priorSnapshot.SourceFiles.Key(DependencyGraphType.File) + //let lastFileIndex = (parsedInputs |> Array.length) - 1 + //caches.DependencyGraph.Get(key, computeDependencyGraph parsedInputs (Graph.subGraphFor lastFileIndex)) + caches.DependencyGraph.Get( + key, + computeDependencyGraph + tcConfig + (priorSnapshot.SourceFiles |> Seq.map (fun f -> f.ParsedInput)) + (removeImplFilesThatHaveSignaturesExceptLastOne priorSnapshot) + ) + + let ComputeDependencyGraphForProject (tcConfig: TcConfig) (projectSnapshot: ProjectSnapshotBase) = + + let key = projectSnapshot.SourceFiles.Key(DependencyGraphType.Project) + //caches.DependencyGraph.Get(key, computeDependencyGraph parsedInputs (removeImplFilesThatHaveSignatures projectSnapshot)) + caches.DependencyGraph.Get( + key, + computeDependencyGraph tcConfig (projectSnapshot.SourceFiles |> Seq.map (fun f -> f.ParsedInput)) id + ) + + let ComputeTcIntermediate + (projectSnapshot: ProjectSnapshotBase) + (dependencyGraph: Graph) + (index: FileIndex) + (nodeToCheck: NodeToTypeCheck) + bootstrapInfo + (prevTcInfo: TcInfo) + = + + ignore dependencyGraph + + let key = projectSnapshot.FileKey(index).WithExtraVersion(bootstrapInfo.Id) + + let _label, _k, _version = key.GetLabel(), key.GetKey(), key.GetVersion() + + caches.TcIntermediate.Get( + key, + node { + + let file = projectSnapshot.SourceFiles[index] + + let input = file.ParsedInput + let fileName = file.FileName + + use _ = + Activity.start + "ComputeTcIntermediate" + [| + Activity.Tags.fileName, fileName |> Path.GetFileName + "key", key.GetLabel() + "version", "-" // key.GetVersion() + |] + + beforeFileChecked.Trigger(fileName, Unchecked.defaultof<_>) + + let tcConfig = bootstrapInfo.TcConfig + let tcGlobals = bootstrapInfo.TcGlobals + let tcImports = bootstrapInfo.TcImports + + let mainInputFileName = file.FileName + let sourceText = file.SourceText + let parsedMainInput = file.ParsedInput + + // Initialize the error handler + let errHandler = + ParseAndCheckFile.DiagnosticsHandler( + true, + mainInputFileName, + tcConfig.diagnosticsOptions, + sourceText, + suggestNamesForErrors, + tcConfig.flatErrors + ) + + use _ = + new CompilationGlobalsScope(errHandler.DiagnosticsLogger, BuildPhase.TypeCheck) + + // Apply nowarns to tcConfig (may generate errors, so ensure diagnosticsLogger is installed) + let tcConfig = + ApplyNoWarnsToTcConfig(tcConfig, parsedMainInput, Path.GetDirectoryName mainInputFileName) + + // update the error handler with the modified tcConfig + errHandler.DiagnosticOptions <- tcConfig.diagnosticsOptions + + let diagnosticsLogger = errHandler.DiagnosticsLogger + + //let capturingDiagnosticsLogger = CapturingDiagnosticsLogger("TypeCheck") + + //let diagnosticsLogger = + // GetDiagnosticsLoggerFilteringByScopedPragmas( + // false, + // input.ScopedPragmas, + // tcConfig.diagnosticsOptions, + // capturingDiagnosticsLogger + // ) + + //use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.TypeCheck) + + //beforeFileChecked.Trigger fileName + + ApplyMetaCommandsFromInputToTcConfig(tcConfig, input, Path.GetDirectoryName fileName, tcImports.DependencyProvider) + |> ignore + + let sink = TcResultsSinkImpl(tcGlobals) + + let hadParseErrors = not (Array.isEmpty file.ParseErrors) + + let input, moduleNamesDict = + DeduplicateParsedInputModuleName prevTcInfo.moduleNamesDict input + + //let! ct = NodeCode.CancellationToken + + try + //do! maxParallelismSemaphore.WaitAsync(ct) |> NodeCode.AwaitTask + + let! finisher = + CheckOneInputWithCallback + nodeToCheck + ((fun () -> hadParseErrors || diagnosticsLogger.ErrorCount > 0), + tcConfig, + tcImports, + tcGlobals, + None, + TcResultsSink.WithSink sink, + prevTcInfo.tcState, + input, + true) + |> Cancellable.toAsync + |> NodeCode.AwaitAsync + + //fileChecked.Trigger fileName + + let newErrors = + Array.append file.ParseErrors (errHandler.CollectedPhasedDiagnostics) + + fileChecked.Trigger(fileName, Unchecked.defaultof<_>) + + return + { + finisher = finisher + moduleNamesDict = moduleNamesDict + tcDiagnosticsRev = [ newErrors ] + tcDependencyFiles = [ fileName ] + sink = sink + } + finally + () + //maxParallelismSemaphore.Release() |> ignore + } + ) + + let processGraphNode projectSnapshot bootstrapInfo dependencyFiles collectSinks (fileNode: NodeToTypeCheck) tcInfo = + // TODO: should this be node? + async { + match fileNode with + | NodeToTypeCheck.PhysicalFile index -> + + let! tcIntermediate = + ComputeTcIntermediate projectSnapshot dependencyFiles index fileNode bootstrapInfo tcInfo + |> Async.AwaitNodeCode + + let (Finisher(node = node; finisher = finisher)) = tcIntermediate.finisher + + return + Finisher( + node, + (fun tcInfo -> + + if tcInfo.stateContainsNodes |> Set.contains fileNode then + failwith $"Oops!" + + //if + // tcInfo.stateContainsNodes + // Signature files don't have to be right above the impl file... if we need this check then + // we need to do it differently + // |> Set.contains (NodeToTypeCheck.ArtificialImplFile(index - 1)) + //then + // failwith $"Oops???" + + let partialResult, tcState = finisher tcInfo.tcState + + let tcEnv, topAttribs, _checkImplFileOpt, ccuSigForFile = partialResult + + let tcEnvAtEndOfFile = + if keepAllBackgroundResolutions then + tcEnv + else + tcState.TcEnvFromImpls + + partialResult, + { tcInfo with + tcState = tcState + tcEnvAtEndOfFile = tcEnvAtEndOfFile + moduleNamesDict = tcIntermediate.moduleNamesDict + topAttribs = Some topAttribs + tcDiagnosticsRev = tcIntermediate.tcDiagnosticsRev @ tcInfo.tcDiagnosticsRev + tcDependencyFiles = tcIntermediate.tcDependencyFiles @ tcInfo.tcDependencyFiles + latestCcuSigForFile = Some ccuSigForFile + graphNode = Some node + stateContainsNodes = tcInfo.stateContainsNodes |> Set.add node + sink = + if collectSinks then + tcIntermediate.sink :: tcInfo.sink + else + [ tcIntermediate.sink ] + }) + ) + + | NodeToTypeCheck.ArtificialImplFile index -> + return + Finisher( + fileNode, + (fun tcInfo -> + + if tcInfo.stateContainsNodes |> Set.contains fileNode then + failwith $"Oops!" + + if + tcInfo.stateContainsNodes + |> Set.contains (NodeToTypeCheck.PhysicalFile(index + 1)) + then + failwith $"Oops!!!" + + let parsedInput = projectSnapshot.SourceFiles[index].ParsedInput + let prefixPathOpt = None + // Retrieve the type-checked signature information and add it to the TcEnvFromImpls. + let partialResult, tcState = + AddSignatureResultToTcImplEnv + (bootstrapInfo.TcImports, + bootstrapInfo.TcGlobals, + prefixPathOpt, + TcResultsSink.NoSink, + tcInfo.tcState, + parsedInput) + tcInfo.tcState + + let tcEnv, topAttribs, _checkImplFileOpt, ccuSigForFile = partialResult + + let tcEnvAtEndOfFile = + if keepAllBackgroundResolutions then + tcEnv + else + tcState.TcEnvFromImpls + + partialResult, + { tcInfo with + tcState = tcState + tcEnvAtEndOfFile = tcEnvAtEndOfFile + topAttribs = Some topAttribs + latestCcuSigForFile = Some ccuSigForFile + graphNode = Some fileNode + stateContainsNodes = tcInfo.stateContainsNodes |> Set.add fileNode + }) + ) + + } + + let parseSourceFiles (projectSnapshot: ProjectSnapshotWithSources) tcConfig = + node { + let! parsedInputs = + projectSnapshot.SourceFiles + |> Seq.map (ComputeParseFile projectSnapshot tcConfig) + |> NodeCode.Parallel + + return ProjectSnapshotBase<_>(projectSnapshot.ProjectCore, parsedInputs |> Array.toList) + } + + // Type check file and all its dependencies + let ComputeTcLastFile (bootstrapInfo: BootstrapInfo) (projectSnapshot: ProjectSnapshotWithSources) = + let fileName = projectSnapshot.SourceFiles |> List.last |> (fun f -> f.FileName) + + caches.TcLastFile.Get( + projectSnapshot.FileKey fileName, + node { + let file = projectSnapshot.SourceFiles |> List.last + + use _ = + Activity.start "ComputeTcLastFile" [| Activity.Tags.fileName, file.FileName |> Path.GetFileName |] + + let! projectSnapshot = parseSourceFiles projectSnapshot bootstrapInfo.TcConfig + + let! graph, dependencyFiles = ComputeDependencyGraphForFile bootstrapInfo.TcConfig projectSnapshot + + let! results, tcInfo = + processTypeCheckingGraph + graph + (processGraphNode projectSnapshot bootstrapInfo dependencyFiles false) + bootstrapInfo.InitialTcInfo + |> NodeCode.AwaitAsync + + let lastResult = results |> List.head |> snd + + return lastResult, tcInfo + } + ) + + let getParseResult (projectSnapshot: ProjectSnapshot) creationDiags file (tcConfig: TcConfig) = + node { + let! parsedFile = ComputeParseFile projectSnapshot tcConfig file + + let parseDiagnostics = + DiagnosticHelpers.CreateDiagnostics( + tcConfig.diagnosticsOptions, + false, + file.FileName, + parsedFile.ParseErrors, + suggestNamesForErrors, + tcConfig.flatErrors, + None + ) + + let diagnostics = [| yield! creationDiags; yield! parseDiagnostics |] + + return + FSharpParseFileResults( + diagnostics = diagnostics, + input = parsedFile.ParsedInput, + parseHadErrors = (parseDiagnostics.Length > 0), + // TODO: check if we really need this in parse results + dependencyFiles = [||] + ) + } + + let emptyParseResult fileName diagnostics = + let parseTree = EmptyParsedInput(fileName, (false, false)) + FSharpParseFileResults(diagnostics, parseTree, true, [||]) + + let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: ProjectSnapshot) = + caches.ParseAndCheckFileInProject.Get( + projectSnapshot.FileKey fileName, + node { + + use _ = + Activity.start "ComputeParseAndCheckFileInProject" [| Activity.Tags.fileName, fileName |> Path.GetFileName |] + + match! ComputeBootstrapInfo projectSnapshot with + | None, creationDiags -> return emptyParseResult fileName creationDiags, FSharpCheckFileAnswer.Aborted + + | Some bootstrapInfo, creationDiags -> + + let priorSnapshot = projectSnapshot.UpTo fileName + let! snapshotWithSources = LoadSources bootstrapInfo priorSnapshot + let file = snapshotWithSources.SourceFiles |> List.last + + let! parseResults = getParseResult projectSnapshot creationDiags file bootstrapInfo.TcConfig + + let! result, tcInfo = ComputeTcLastFile bootstrapInfo snapshotWithSources + + let (tcEnv, _topAttribs, checkedImplFileOpt, ccuSigForFile) = result + + let tcState = tcInfo.tcState + + let sink = tcInfo.sink.Head // TODO: don't use head + + let tcResolutions = sink.GetResolutions() + let tcSymbolUses = sink.GetSymbolUses() + let tcOpenDeclarations = sink.GetOpenDeclarations() + + let tcDependencyFiles = [] // TODO add as a set to TcIntermediate + + // TODO: Apparently creating diagnostics can produce further diagnostics. So let's capture those too. Hopefully there is a more elegant solution... + // Probably diagnostics need to be evaluated during typecheck anyway for proper formatting, which might take care of this too. + let extraLogger = CapturingDiagnosticsLogger("DiagnosticsWhileCreatingDiagnostics") + use _ = new CompilationGlobalsScope(extraLogger, BuildPhase.TypeCheck) + + // Apply nowarns to tcConfig (may generate errors, so ensure diagnosticsLogger is installed) + let tcConfig = + ApplyNoWarnsToTcConfig(bootstrapInfo.TcConfig, parseResults.ParseTree, Path.GetDirectoryName fileName) + + let diagnosticsOptions = tcConfig.diagnosticsOptions + + let symbolEnv = + SymbolEnv(bootstrapInfo.TcGlobals, tcState.Ccu, Some tcState.CcuSig, bootstrapInfo.TcImports) + + let tcDiagnostics = + DiagnosticHelpers.CreateDiagnostics( + diagnosticsOptions, + false, + fileName, + tcInfo.TcDiagnostics, + suggestNamesForErrors, + bootstrapInfo.TcConfig.flatErrors, + Some symbolEnv + ) + + let extraDiagnostics = + DiagnosticHelpers.CreateDiagnostics( + diagnosticsOptions, + false, + fileName, + extraLogger.Diagnostics, + suggestNamesForErrors, + bootstrapInfo.TcConfig.flatErrors, + Some symbolEnv + ) + + let tcDiagnostics = + [| yield! creationDiags; yield! extraDiagnostics; yield! tcDiagnostics |] + + let loadClosure = None // TODO: script support + + let typedResults = + FSharpCheckFileResults.Make( + fileName, + projectSnapshot.ProjectFileName, + bootstrapInfo.TcConfig, + bootstrapInfo.TcGlobals, + projectSnapshot.IsIncompleteTypeCheckEnvironment, + None, + projectSnapshot.ToOptions(), + Array.ofList tcDependencyFiles, + creationDiags, + parseResults.Diagnostics, + tcDiagnostics, + keepAssemblyContents, + ccuSigForFile, + tcState.Ccu, + bootstrapInfo.TcImports, + tcEnv.AccessRights, + tcResolutions, + tcSymbolUses, + tcEnv.NameEnv, + loadClosure, + checkedImplFileOpt, + tcOpenDeclarations + ) + + return (parseResults, FSharpCheckFileAnswer.Succeeded typedResults) + } + ) + + let ComputeParseAndCheckAllFilesInProject (bootstrapInfo: BootstrapInfo) (projectSnapshot: ProjectSnapshotWithSources) = + caches.ParseAndCheckAllFilesInProject.Get( + projectSnapshot.FullKey, + node { + use _ = + Activity.start + "ComputeParseAndCheckAllFilesInProject" + [| Activity.Tags.project, projectSnapshot.ProjectFileName |> Path.GetFileName |] + + let! projectSnapshot = parseSourceFiles projectSnapshot bootstrapInfo.TcConfig + + let! graph, dependencyFiles = ComputeDependencyGraphForProject bootstrapInfo.TcConfig projectSnapshot + + return! + processTypeCheckingGraph + graph + (processGraphNode projectSnapshot bootstrapInfo dependencyFiles true) + bootstrapInfo.InitialTcInfo + |> NodeCode.AwaitAsync + } + ) + + let ComputeProjectExtras (bootstrapInfo: BootstrapInfo) (projectSnapshot: ProjectSnapshotWithSources) = + caches.ProjectExtras.Get( + projectSnapshot.SignatureKey, + node { + + let! results, finalInfo = ComputeParseAndCheckAllFilesInProject bootstrapInfo projectSnapshot + + let assemblyName = bootstrapInfo.AssemblyName + let tcConfig = bootstrapInfo.TcConfig + let tcGlobals = bootstrapInfo.TcGlobals + + let results = results |> Seq.sortBy fst |> Seq.map snd |> Seq.toList + + // Finish the checking + let (_tcEnvAtEndOfLastFile, topAttrs, checkedImplFiles, _), tcState = + CheckMultipleInputsFinish(results, finalInfo.tcState) + + let tcState, _, ccuContents = CheckClosedInputSetFinish([], tcState) + + let generatedCcu = tcState.Ccu.CloneWithFinalizedContents(ccuContents) + + // Compute the identity of the generated assembly based on attributes, options etc. + // Some of this is duplicated from fsc.fs + let ilAssemRef = + let publicKey = + try + let signingInfo = ValidateKeySigningAttributes(tcConfig, tcGlobals, topAttrs) + + match GetStrongNameSigner signingInfo with + | None -> None + | Some s -> Some(PublicKey.KeyAsToken(s.PublicKey)) + with exn -> + errorRecoveryNoRange exn + None + + let locale = + TryFindFSharpStringAttribute + tcGlobals + (tcGlobals.FindSysAttrib "System.Reflection.AssemblyCultureAttribute") + topAttrs.assemblyAttrs + + let assemVerFromAttrib = + TryFindFSharpStringAttribute + tcGlobals + (tcGlobals.FindSysAttrib "System.Reflection.AssemblyVersionAttribute") + topAttrs.assemblyAttrs + |> Option.bind (fun v -> + try + Some(parseILVersion v) + with _ -> + None) + + let ver = + match assemVerFromAttrib with + | None -> tcConfig.version.GetVersionInfo(tcConfig.implicitIncludeDir) + | Some v -> v + + ILAssemblyRef.Create(assemblyName, None, publicKey, false, Some ver, locale) + + let assemblyDataResult = + try + // Assemblies containing type provider components can not successfully be used via cross-assembly references. + // We return 'None' for the assembly portion of the cross-assembly reference + let hasTypeProviderAssemblyAttrib = + topAttrs.assemblyAttrs + |> List.exists (fun (Attrib(tcref, _, _, _, _, _, _)) -> + let nm = tcref.CompiledRepresentationForNamedType.BasicQualifiedName + + nm = typeof.FullName) + + if tcState.CreatesGeneratedProvidedTypes || hasTypeProviderAssemblyAttrib then + ProjectAssemblyDataResult.Unavailable true + else + ProjectAssemblyDataResult.Available( + RawFSharpAssemblyDataBackedByLanguageService( + bootstrapInfo.TcConfig, + bootstrapInfo.TcGlobals, + generatedCcu, + bootstrapInfo.OutFile, + topAttrs, + bootstrapInfo.AssemblyName, + ilAssemRef + ) + :> IRawFSharpAssemblyData + ) + with exn -> + errorRecoveryNoRange exn + ProjectAssemblyDataResult.Unavailable true + + return finalInfo, ilAssemRef, assemblyDataResult, checkedImplFiles + } + ) + + let ComputeAssemblyData (projectSnapshot: ProjectSnapshot) fileName = + caches.AssemblyData.Get( + projectSnapshot.SignatureKey, + node { + + try + + let availableOnDiskModifiedTime = + if FileSystem.FileExistsShim fileName then + Some <| FileSystem.GetLastWriteTimeShim fileName + else + None + + // TODO: This kinda works, but the problem is that in order to switch a project to "in-memory" mode + // - some file needs to be edited (this tirggers a re-check, but LastModifiedTimeOnDisk won't change) + // - saved (this will not trigger anything) + // - and then another change has to be made (to any file buffer) - so that recheck is triggered and we get here again + // Until that sequence happens the project will be used from disk (if available). + // To get around it we probably need to detect changes made in the editor and record a timestamp for them. + let shouldUseOnDisk = + availableOnDiskModifiedTime + |> Option.exists (fun t -> t >= projectSnapshot.GetLastModifiedTimeOnDisk()) + + let name = projectSnapshot.ProjectFileName |> Path.GetFileNameWithoutExtension + + if shouldUseOnDisk then + Trace.TraceInformation($"Using assembly on disk: {name}") + return ProjectAssemblyDataResult.Unavailable true + else + match! ComputeBootstrapInfo projectSnapshot with + | None, _ -> + Trace.TraceInformation($"Using assembly on disk (unintentionally): {name}") + return ProjectAssemblyDataResult.Unavailable true + | Some bootstrapInfo, _creationDiags -> + + let! snapshotWithSources = LoadSources bootstrapInfo projectSnapshot + + let! _, _, assemblyDataResult, _ = ComputeProjectExtras bootstrapInfo snapshotWithSources + Trace.TraceInformation($"Using in-memory project reference: {name}") + + return assemblyDataResult + with + | TaskCancelled ex -> return raise ex + | ex -> + errorR (exn ($"Error while computing assembly data for project {projectSnapshot.Label}: {ex}")) + return ProjectAssemblyDataResult.Unavailable true + } + ) + + let ComputeParseAndCheckProject (projectSnapshot: ProjectSnapshot) = + caches.ParseAndCheckProject.Get( + projectSnapshot.FullKey, + node { + + match! ComputeBootstrapInfo projectSnapshot with + | None, creationDiags -> + return FSharpCheckProjectResults(projectSnapshot.ProjectFileName, None, keepAssemblyContents, creationDiags, None) + | Some bootstrapInfo, creationDiags -> + + let! snapshotWithSources = LoadSources bootstrapInfo projectSnapshot + + let! tcInfo, ilAssemRef, assemblyDataResult, checkedImplFiles = ComputeProjectExtras bootstrapInfo snapshotWithSources + + let diagnosticsOptions = bootstrapInfo.TcConfig.diagnosticsOptions + let fileName = DummyFileNameForRangesWithoutASpecificLocation + + let topAttribs = tcInfo.topAttribs + let tcState = tcInfo.tcState + let tcEnvAtEnd = tcInfo.tcEnvAtEndOfFile + let tcDiagnostics = tcInfo.TcDiagnostics + let tcDependencyFiles = tcInfo.tcDependencyFiles + + let symbolEnv = + SymbolEnv(bootstrapInfo.TcGlobals, tcInfo.tcState.Ccu, Some tcInfo.tcState.CcuSig, bootstrapInfo.TcImports) + |> Some + + let tcDiagnostics = + DiagnosticHelpers.CreateDiagnostics( + diagnosticsOptions, + true, + fileName, + tcDiagnostics, + suggestNamesForErrors, + bootstrapInfo.TcConfig.flatErrors, + symbolEnv + ) + + let diagnostics = [| yield! creationDiags; yield! tcDiagnostics |] + + let getAssemblyData () = + match assemblyDataResult with + | ProjectAssemblyDataResult.Available data -> Some data + | _ -> None + + let symbolUses = tcInfo.sink |> Seq.map (fun sink -> sink.GetSymbolUses()) + + let details = + (bootstrapInfo.TcGlobals, + bootstrapInfo.TcImports, + tcState.Ccu, + tcState.CcuSig, + Choice2Of2(async.Return symbolUses), + topAttribs, + getAssemblyData, + ilAssemRef, + tcEnvAtEnd.AccessRights, + Some checkedImplFiles, + Array.ofList tcDependencyFiles, + projectSnapshot.ToOptions()) + + let results = + FSharpCheckProjectResults( + projectSnapshot.ProjectFileName, + Some bootstrapInfo.TcConfig, + keepAssemblyContents, + diagnostics, + Some details + ) + + return results + } + ) + + let tryGetSink (fileName: string) (projectSnapshot: ProjectSnapshot) = + node { + match! ComputeBootstrapInfo projectSnapshot with + | None, _ -> return None + | Some bootstrapInfo, _creationDiags -> + + let! snapshotWithSources = projectSnapshot.UpTo fileName |> LoadSources bootstrapInfo + + let! _, tcInfo = ComputeTcLastFile bootstrapInfo snapshotWithSources + + return tcInfo.sink |> List.tryHead |> Option.map (fun sink -> sink, bootstrapInfo) + } + + let ComputeSemanticClassification (fileName: string, projectSnapshot: ProjectSnapshot) = + caches.SemanticClassification.Get( + projectSnapshot.FileKey fileName, + node { + use _ = + Activity.start "ComputeSemanticClassification" [| Activity.Tags.fileName, fileName |> Path.GetFileName |] + + let! sinkOpt = tryGetSink fileName projectSnapshot + + return + sinkOpt + |> Option.bind (fun (sink, bootstrapInfo) -> + let sResolutions = sink.GetResolutions() + + let semanticClassification = + sResolutions.GetSemanticClassification( + bootstrapInfo.TcGlobals, + bootstrapInfo.TcImports.GetImportMap(), + sink.GetFormatSpecifierLocations(), + None + ) + + let sckBuilder = SemanticClassificationKeyStoreBuilder() + sckBuilder.WriteAll semanticClassification + + sckBuilder.TryBuildAndReset()) + |> Option.map (fun sck -> sck.GetView()) + } + ) + + let ComputeItemKeyStore (fileName: string, projectSnapshot: ProjectSnapshot) = + caches.ItemKeyStore.Get( + projectSnapshot.FileKey fileName, + node { + use _ = + Activity.start "ComputeItemKeyStore" [| Activity.Tags.fileName, fileName |> Path.GetFileName |] + + let! sinkOpt = tryGetSink fileName projectSnapshot + + return + sinkOpt + |> Option.bind (fun (sink, { TcGlobals = g }) -> + let sResolutions = sink.GetResolutions() + + let builder = ItemKeyStoreBuilder(g) + + let preventDuplicates = + HashSet( + { new IEqualityComparer with + member _.Equals((s1, e1): struct (pos * pos), (s2, e2): struct (pos * pos)) = + Position.posEq s1 s2 && Position.posEq e1 e2 + + member _.GetHashCode o = o.GetHashCode() + } + ) + + sResolutions.CapturedNameResolutions + |> Seq.iter (fun cnr -> + let r = cnr.Range + + if preventDuplicates.Add struct (r.Start, r.End) then + builder.Write(cnr.Range, cnr.Item)) + + builder.TryBuildAndReset()) + } + ) + + member _.ParseFile(fileName, projectSnapshot: ProjectSnapshot, _userOpName) = + node { + //use _ = + // Activity.start "ParseFile" [| Activity.Tags.fileName, fileName |> Path.GetFileName |] + + // TODO: might need to deal with exceptions here: + let tcConfigB, sourceFileNames, _ = ComputeTcConfigBuilder projectSnapshot + + let tcConfig = TcConfig.Create(tcConfigB, validate = true) + + let _index, fileSnapshot = + projectSnapshot.SourceFiles + |> Seq.mapi pair + |> Seq.tryFind (fun (_, f) -> f.FileName = fileName) + |> Option.defaultWith (fun () -> failwith $"File not found: {fileName}") + + let isExe = tcConfig.target.IsExe + let isLastCompiland = fileName = (sourceFileNames |> List.last) + + let! file = LoadSource fileSnapshot isExe isLastCompiland + let! parseResult = getParseResult projectSnapshot Seq.empty file tcConfig + return parseResult + } + + member _.ParseAndCheckFileInProject(fileName: string, projectSnapshot: ProjectSnapshot, userOpName: string) = + ignore userOpName + ComputeParseAndCheckFileInProject fileName projectSnapshot + + member _.FindReferencesInFile(fileName: string, projectSnapshot: ProjectSnapshot, symbol: FSharpSymbol, userOpName: string) = + ignore userOpName + + node { + match! ComputeItemKeyStore(fileName, projectSnapshot) with + | None -> return Seq.empty + | Some itemKeyStore -> return itemKeyStore.FindAll symbol.Item + } + + member _.GetAssemblyData(projectSnapshot: ProjectSnapshot, fileName, _userOpName) = + ComputeAssemblyData projectSnapshot fileName + + member _.Caches = caches + + member _.SetCacheSizeFactor(sizeFactor: int) = + if sizeFactor <> caches.SizeFactor then + caches <- CompilerCaches(sizeFactor) + + interface IBackgroundCompiler with + + member this.CheckFileInProject + ( + parseResults: FSharpParseFileResults, + fileName: string, + fileVersion: int, + sourceText: ISourceText, + options: FSharpProjectOptions, + userOpName: string + ) : NodeCode = + node { + let! snapshot = + FSharpProjectSnapshot.FromOptions(options, fileName, fileVersion, sourceText) + |> NodeCode.AwaitAsync + + ignore parseResults + + let! _, result = this.ParseAndCheckFileInProject(fileName, snapshot.ProjectSnapshot, userOpName) + + return result + } + + member this.CheckFileInProjectAllowingStaleCachedResults + ( + parseResults: FSharpParseFileResults, + fileName: string, + fileVersion: int, + sourceText: ISourceText, + options: FSharpProjectOptions, + userOpName: string + ) : NodeCode = + node { + let! snapshot = + FSharpProjectSnapshot.FromOptions(options, fileName, fileVersion, sourceText) + |> NodeCode.AwaitAsync + + ignore parseResults + + let! _, result = this.ParseAndCheckFileInProject(fileName, snapshot.ProjectSnapshot, userOpName) + + return Some result + } + + member this.ClearCache(projects: FSharpProjectIdentifier seq, userOpName: string) : unit = + use _ = + Activity.start "TransparentCompiler.ClearCache" [| Activity.Tags.userOpName, userOpName |] + + this.Caches.Clear( + projects + |> Seq.map (function + | FSharpProjectIdentifier(x, y) -> (x, y)) + |> Set + ) + + member this.ClearCache(options: seq, userOpName: string) : unit = + use _ = + Activity.start "TransparentCompiler.ClearCache" [| Activity.Tags.userOpName, userOpName |] + + backgroundCompiler.ClearCache(options, userOpName) + this.Caches.Clear(options |> Seq.map (fun o -> o.GetProjectIdentifier()) |> Set) + + member _.ClearCaches() : unit = + backgroundCompiler.ClearCaches() + caches <- CompilerCaches(100) // TODO: check + + member _.DownsizeCaches() : unit = backgroundCompiler.DownsizeCaches() + + member _.BeforeBackgroundFileCheck = beforeFileChecked.Publish + + member _.FileParsed = fileParsed.Publish + + member _.FileChecked = fileChecked.Publish + + member _.ProjectChecked = projectChecked.Publish + + member this.FindReferencesInFile + ( + fileName: string, + options: FSharpProjectOptions, + symbol: FSharpSymbol, + canInvalidateProject: bool, + userOpName: string + ) : NodeCode> = + node { + ignore canInvalidateProject + let! snapshot = FSharpProjectSnapshot.FromOptions options |> NodeCode.AwaitAsync + + return! this.FindReferencesInFile(fileName, snapshot.ProjectSnapshot, symbol, userOpName) + } + + member this.FindReferencesInFile(fileName, projectSnapshot, symbol, userOpName) = + this.FindReferencesInFile(fileName, projectSnapshot.ProjectSnapshot, symbol, userOpName) + + member _.FrameworkImportsCache: FrameworkImportsCache = + backgroundCompiler.FrameworkImportsCache + + member this.GetAssemblyData(options: FSharpProjectOptions, fileName, userOpName: string) : NodeCode = + node { + let! snapshot = FSharpProjectSnapshot.FromOptions options |> NodeCode.AwaitAsync + return! this.GetAssemblyData(snapshot.ProjectSnapshot, fileName, userOpName) + } + + member this.GetAssemblyData + ( + projectSnapshot: FSharpProjectSnapshot, + fileName, + userOpName: string + ) : NodeCode = + this.GetAssemblyData(projectSnapshot.ProjectSnapshot, fileName, userOpName) + + member this.GetBackgroundCheckResultsForFileInProject + ( + fileName: string, + options: FSharpProjectOptions, + userOpName: string + ) : NodeCode = + node { + let! snapshot = FSharpProjectSnapshot.FromOptions options |> NodeCode.AwaitAsync + + match! this.ParseAndCheckFileInProject(fileName, snapshot.ProjectSnapshot, userOpName) with + | parseResult, FSharpCheckFileAnswer.Succeeded checkResult -> return parseResult, checkResult + | parseResult, FSharpCheckFileAnswer.Aborted -> return parseResult, FSharpCheckFileResults.MakeEmpty(fileName, [||], true) + } + + member this.GetBackgroundParseResultsForFileInProject + ( + fileName: string, + options: FSharpProjectOptions, + userOpName: string + ) : NodeCode = + node { + let! snapshot = FSharpProjectSnapshot.FromOptions options |> NodeCode.AwaitAsync + return! this.ParseFile(fileName, snapshot.ProjectSnapshot, userOpName) + } + + member this.GetCachedCheckFileResult + ( + builder: IncrementalBuilder, + fileName: string, + sourceText: ISourceText, + options: FSharpProjectOptions + ) : NodeCode<(FSharpParseFileResults * FSharpCheckFileResults) option> = + node { + ignore builder + + let! snapshot = + FSharpProjectSnapshot.FromOptions(options, fileName, 1, sourceText) + |> NodeCode.AwaitAsync + + match! this.ParseAndCheckFileInProject(fileName, snapshot.ProjectSnapshot, "GetCachedCheckFileResult") with + | parseResult, FSharpCheckFileAnswer.Succeeded checkResult -> return Some(parseResult, checkResult) + | _, FSharpCheckFileAnswer.Aborted -> return None + } + + member this.GetProjectOptionsFromScript + ( + fileName: string, + sourceText: ISourceText, + previewEnabled: bool option, + loadedTimeStamp: DateTime option, + otherFlags: string array option, + useFsiAuxLib: bool option, + useSdkRefs: bool option, + sdkDirOverride: string option, + assumeDotNetFramework: bool option, + optionsStamp: int64 option, + userOpName: string + ) : Async = + backgroundCompiler.GetProjectOptionsFromScript( + fileName, + sourceText, + previewEnabled, + loadedTimeStamp, + otherFlags, + useFsiAuxLib, + useSdkRefs, + sdkDirOverride, + assumeDotNetFramework, + optionsStamp, + userOpName + ) + + member this.GetSemanticClassificationForFile(fileName: string, snapshot: FSharpProjectSnapshot, userOpName: string) = + node { + ignore userOpName + return! ComputeSemanticClassification(fileName, snapshot.ProjectSnapshot) + } + + member this.GetSemanticClassificationForFile + ( + fileName: string, + options: FSharpProjectOptions, + userOpName: string + ) : NodeCode = + node { + ignore userOpName + let! snapshot = FSharpProjectSnapshot.FromOptions options |> NodeCode.AwaitAsync + return! ComputeSemanticClassification(fileName, snapshot.ProjectSnapshot) + } + + member this.InvalidateConfiguration(options: FSharpProjectOptions, userOpName: string) : unit = + backgroundCompiler.InvalidateConfiguration(options, userOpName) + + member this.NotifyFileChanged(fileName: string, options: FSharpProjectOptions, userOpName: string) : NodeCode = + backgroundCompiler.NotifyFileChanged(fileName, options, userOpName) + + member this.NotifyProjectCleaned(options: FSharpProjectOptions, userOpName: string) : Async = + backgroundCompiler.NotifyProjectCleaned(options, userOpName) + + member this.ParseAndCheckFileInProject + ( + fileName: string, + fileVersion: int, + sourceText: ISourceText, + options: FSharpProjectOptions, + userOpName: string + ) : NodeCode = + node { + let! snapshot = + FSharpProjectSnapshot.FromOptions(options, fileName, fileVersion, sourceText) + |> NodeCode.AwaitAsync + + return! this.ParseAndCheckFileInProject(fileName, snapshot.ProjectSnapshot, userOpName) + } + + member this.ParseAndCheckFileInProject(fileName: string, projectSnapshot: FSharpProjectSnapshot, userOpName: string) = + this.ParseAndCheckFileInProject(fileName, projectSnapshot.ProjectSnapshot, userOpName) + + member this.ParseAndCheckProject(options: FSharpProjectOptions, userOpName: string) : NodeCode = + node { + ignore userOpName + let! snapshot = FSharpProjectSnapshot.FromOptions options |> NodeCode.AwaitAsync + return! ComputeParseAndCheckProject snapshot.ProjectSnapshot + } + + member this.ParseAndCheckProject(projectSnapshot: FSharpProjectSnapshot, userOpName: string) : NodeCode = + node { + ignore userOpName + return! ComputeParseAndCheckProject projectSnapshot.ProjectSnapshot + } + + member this.ParseFile(fileName, projectSnapshot, userOpName) = + this.ParseFile(fileName, projectSnapshot.ProjectSnapshot, userOpName) + |> Async.AwaitNodeCode + + member this.ParseFile + ( + fileName: string, + sourceText: ISourceText, + options: FSharpParsingOptions, + cache: bool, + flatErrors: bool, + userOpName: string + ) = + backgroundCompiler.ParseFile(fileName, sourceText, options, cache, flatErrors, userOpName) + + member this.TryGetRecentCheckResultsForFile + ( + fileName: string, + options: FSharpProjectOptions, + sourceText: ISourceText option, + userOpName: string + ) : (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option = + backgroundCompiler.TryGetRecentCheckResultsForFile(fileName, options, sourceText, userOpName) diff --git a/src/Compiler/Service/TransparentCompiler.fsi b/src/Compiler/Service/TransparentCompiler.fsi new file mode 100644 index 00000000000..00167ccc67f --- /dev/null +++ b/src/Compiler/Service/TransparentCompiler.fsi @@ -0,0 +1,175 @@ +namespace FSharp.Compiler.CodeAnalysis.TransparentCompiler + +open Internal.Utilities.Collections + +open FSharp.Compiler.AbstractIL.ILBinaryReader +open FSharp.Compiler.BuildGraph +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.CompilerConfig +open FSharp.Compiler.CompilerImports +open FSharp.Compiler.CheckBasics +open FSharp.Compiler.Diagnostics +open FSharp.Compiler.DiagnosticsLogger +open FSharp.Compiler.ScriptClosure +open FSharp.Compiler.Symbols +open FSharp.Compiler.TcGlobals +open FSharp.Compiler.Text +open FSharp.Compiler.ParseAndCheckInputs +open FSharp.Compiler.GraphChecking +open FSharp.Compiler.Syntax +open FSharp.Compiler.NameResolution +open FSharp.Compiler.TypedTree +open FSharp.Compiler.CheckDeclarations +open FSharp.Compiler.EditorServices + +/// Accumulated results of type checking. The minimum amount of state in order to continue type-checking following files. +[] +type internal TcInfo = + { + tcState: TcState + tcEnvAtEndOfFile: TcEnv + + /// Disambiguation table for module names + moduleNamesDict: ModuleNamesDict + + topAttribs: TopAttribs option + + latestCcuSigForFile: ModuleOrNamespaceType option + + /// Accumulated diagnostics, last file first + tcDiagnosticsRev: (PhasedDiagnostic * FSharpDiagnosticSeverity)[] list + + tcDependencyFiles: string list + + sigNameOpt: (string * QualifiedNameOfFile) option + + graphNode: NodeToTypeCheck option + + stateContainsNodes: Set + + sink: TcResultsSinkImpl list + } + +[] +type internal TcIntermediate = + { + finisher: Finisher + + /// Disambiguation table for module names + moduleNamesDict: ModuleNamesDict + + /// Accumulated diagnostics, last file first + tcDiagnosticsRev: (PhasedDiagnostic * FSharpDiagnosticSeverity) array list + tcDependencyFiles: string list + sink: TcResultsSinkImpl + } + +/// Things we need to start parsing and checking files for a given project snapshot +type internal BootstrapInfo = + { Id: int + AssemblyName: string + OutFile: string + TcConfig: TcConfig + TcImports: TcImports + TcGlobals: TcGlobals + InitialTcInfo: TcInfo + LoadedSources: (range * ProjectSnapshot.FSharpFileSnapshot) list + LoadClosure: LoadClosure option + LastFileName: string } + +type internal TcIntermediateResult = TcInfo * TcResultsSinkImpl * CheckedImplFile option * string + +[] +type internal DependencyGraphType = + + /// A dependency graph for a single file - it will be missing files which this file does not depend on + | File + + /// A dependency graph for a project - it will contain all files in the project + | Project + +[] +type internal Extensions = + + [] + static member Key: + fileSnapshots: #ProjectSnapshot.IFileSnapshot list * ?extraKeyFlag: DependencyGraphType -> + ICacheKey<(DependencyGraphType option * byte array), string> + +type internal CompilerCaches = + + new: sizeFactor: int -> CompilerCaches + + member AssemblyData: AsyncMemoize<(string * string), (string * string), ProjectAssemblyDataResult> + + member BootstrapInfo: AsyncMemoize<(string * string), string, (BootstrapInfo option * FSharpDiagnostic array)> + + member BootstrapInfoStatic: + AsyncMemoize<(string * string), (string * string), (int * TcImports * TcGlobals * TcInfo * Event)> + + member DependencyGraph: + AsyncMemoize<(DependencyGraphType option * byte array), string, (Graph * Graph)> + + member FrameworkImports: AsyncMemoize + + member ItemKeyStore: AsyncMemoize<(string * (string * string)), string, ItemKeyStore option> + + member ParseAndCheckAllFilesInProject: AsyncMemoizeDisabled + + member ParseAndCheckFileInProject: + AsyncMemoize<(string * (string * string)), string, (FSharpParseFileResults * FSharpCheckFileAnswer)> + + member ParseAndCheckProject: AsyncMemoize<(string * string), string, FSharpCheckProjectResults> + + member ParseFile: + AsyncMemoize<((string * string) * string), (string * string * bool), ProjectSnapshot.FSharpParsedFile> + + member ProjectExtras: AsyncMemoizeDisabled + + member SemanticClassification: AsyncMemoize<(string * (string * string)), string, SemanticClassificationView option> + + member SizeFactor: int + + member TcIntermediate: AsyncMemoize<(string * (string * string)), (string * int), TcIntermediate> + + member TcLastFile: AsyncMemoizeDisabled + +type internal TransparentCompiler = + interface IBackgroundCompiler + + new: + legacyReferenceResolver: LegacyReferenceResolver * + projectCacheSize: int * + keepAssemblyContents: bool * + keepAllBackgroundResolutions: bool * + tryGetMetadataSnapshot: ILReaderTryGetMetadataSnapshot * + suggestNamesForErrors: bool * + keepAllBackgroundSymbolUses: bool * + enableBackgroundItemKeyStoreAndSemanticClassification: bool * + enablePartialTypeChecking: bool * + parallelReferenceResolution: ParallelReferenceResolution * + captureIdentifiersWhenParsing: bool * + getSource: (string -> Async) option * + useChangeNotifications: bool * + useSyntaxTreeCache: bool -> + TransparentCompiler + + member FindReferencesInFile: + fileName: string * projectSnapshot: ProjectSnapshot.ProjectSnapshot * symbol: FSharpSymbol * userOpName: string -> + NodeCode + + member GetAssemblyData: + projectSnapshot: ProjectSnapshot.ProjectSnapshot * fileName: string * _userOpName: string -> + NodeCode + + member ParseAndCheckFileInProject: + fileName: string * projectSnapshot: ProjectSnapshot.ProjectSnapshot * userOpName: string -> + NodeCode + + member ParseFile: + fileName: string * projectSnapshot: ProjectSnapshot.ProjectSnapshot * _userOpName: 'a -> + NodeCode + + member SetCacheSizeFactor: sizeFactor: int -> unit + + member Caches: CompilerCaches diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs index c5b6e64ffdc..492ff2da497 100644 --- a/src/Compiler/Service/service.fs +++ b/src/Compiler/Service/service.fs @@ -17,6 +17,7 @@ open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.ILBinaryReader open FSharp.Compiler.AbstractIL.ILDynamicAssemblyWriter open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.CodeAnalysis.TransparentCompiler open FSharp.Compiler.CompilerConfig open FSharp.Compiler.CompilerDiagnostics open FSharp.Compiler.CompilerImports @@ -36,19 +37,6 @@ open FSharp.Compiler.Text.Range open FSharp.Compiler.TcGlobals open FSharp.Compiler.BuildGraph -[] -module EnvMisc = - let braceMatchCacheSize = GetEnvInteger "FCS_BraceMatchCacheSize" 5 - let parseFileCacheSize = GetEnvInteger "FCS_ParseFileCacheSize" 2 - let checkFileInProjectCacheSize = GetEnvInteger "FCS_CheckFileInProjectCacheSize" 10 - - let projectCacheSizeDefault = GetEnvInteger "FCS_ProjectCacheSizeDefault" 3 - let frameworkTcImportsCacheStrongSize = GetEnvInteger "FCS_frameworkTcImportsCacheStrongSizeDefault" 8 - -//---------------------------------------------------------------------------- -// BackgroundCompiler -// - [] type DocumentSource = | FileSystem @@ -58,46 +46,6 @@ type DocumentSource = [] type IsResultObsolete = IsResultObsolete of (unit -> bool) -[] -module Helpers = - - /// Determine whether two (fileName,options) keys are identical w.r.t. affect on checking - let AreSameForChecking2 ((fileName1: string, options1: FSharpProjectOptions), (fileName2, options2)) = - (fileName1 = fileName2) - && FSharpProjectOptions.AreSameForChecking(options1, options2) - - /// Determine whether two (fileName,options) keys should be identical w.r.t. resource usage - let AreSubsumable2 ((fileName1: string, o1: FSharpProjectOptions), (fileName2: string, o2: FSharpProjectOptions)) = - (fileName1 = fileName2) && FSharpProjectOptions.UseSameProject(o1, o2) - - /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. parsing - let AreSameForParsing ((fileName1: string, source1Hash: int64, options1), (fileName2, source2Hash, options2)) = - fileName1 = fileName2 && options1 = options2 && source1Hash = source2Hash - - let AreSimilarForParsing ((fileName1, _, _), (fileName2, _, _)) = fileName1 = fileName2 - - /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. checking - let AreSameForChecking3 ((fileName1: string, source1Hash: int64, options1: FSharpProjectOptions), (fileName2, source2Hash, options2)) = - (fileName1 = fileName2) - && FSharpProjectOptions.AreSameForChecking(options1, options2) - && source1Hash = source2Hash - - /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. resource usage - let AreSubsumable3 ((fileName1: string, _, o1: FSharpProjectOptions), (fileName2: string, _, o2: FSharpProjectOptions)) = - (fileName1 = fileName2) && FSharpProjectOptions.UseSameProject(o1, o2) - - /// If a symbol is an attribute check if given set of names contains its name without the Attribute suffix - let rec NamesContainAttribute (symbol: FSharpSymbol) names = - match symbol with - | :? FSharpMemberOrFunctionOrValue as mofov -> - mofov.DeclaringEntity - |> Option.map (fun entity -> NamesContainAttribute entity names) - |> Option.defaultValue false - | :? FSharpEntity as entity when entity.IsAttributeType && symbol.DisplayNameCore.EndsWithOrdinal "Attribute" -> - let nameWithoutAttribute = String.dropSuffix symbol.DisplayNameCore "Attribute" - names |> Set.contains nameWithoutAttribute - | _ -> false - module CompileHelpers = let mkCompilationDiagnosticsHandlers (flatErrors) = let diagnostics = ResizeArray<_>() @@ -165,1190 +113,6 @@ module CompileHelpers = Console.SetError error | None -> () -type SourceTextHash = int64 -type CacheStamp = int64 -type FileName = string -type FilePath = string -type ProjectPath = string -type FileVersion = int - -type ParseCacheLockToken() = - interface LockToken - -type ScriptClosureCacheToken() = - interface LockToken - -type CheckFileCacheKey = FileName * SourceTextHash * FSharpProjectOptions -type CheckFileCacheValue = FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash * DateTime - -// There is only one instance of this type, held in FSharpChecker -type BackgroundCompiler - ( - legacyReferenceResolver, - projectCacheSize, - keepAssemblyContents, - keepAllBackgroundResolutions, - tryGetMetadataSnapshot, - suggestNamesForErrors, - keepAllBackgroundSymbolUses, - enableBackgroundItemKeyStoreAndSemanticClassification, - enablePartialTypeChecking, - parallelReferenceResolution, - captureIdentifiersWhenParsing, - getSource: (string -> Async) option, - useChangeNotifications, - useSyntaxTreeCache - ) as self = - - let beforeFileChecked = Event() - let fileParsed = Event() - let fileChecked = Event() - let projectChecked = Event() - - // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.backgroundCompiler.scriptClosureCache - /// Information about the derived script closure. - let scriptClosureCache = - MruCache( - projectCacheSize, - areSame = FSharpProjectOptions.AreSameForChecking, - areSimilar = FSharpProjectOptions.UseSameProject - ) - - let frameworkTcImportsCache = FrameworkImportsCache(frameworkTcImportsCacheStrongSize) - - // We currently share one global dependency provider for all scripts for the FSharpChecker. - // For projects, one is used per project. - // - // Sharing one for all scripts is necessary for good performance from GetProjectOptionsFromScript, - // which requires a dependency provider to process through the project options prior to working out - // if the cached incremental builder can be used for the project. - let dependencyProviderForScripts = new DependencyProvider() - - let getProjectReferences (options: FSharpProjectOptions) userOpName = - [ - for r in options.ReferencedProjects do - - match r with - | FSharpReferencedProject.FSharpReference(nm, opts) -> - // Don't use cross-project references for FSharp.Core, since various bits of code - // require a concrete FSharp.Core to exist on-disk. The only solutions that have - // these cross-project references to FSharp.Core are VisualFSharp.sln and FSharp.sln. The ramification - // of this is that you need to build FSharp.Core to get intellisense in those projects. - - if - (try - Path.GetFileNameWithoutExtension(nm) - with _ -> - "") - <> GetFSharpCoreLibraryName() - then - { new IProjectReference with - member x.EvaluateRawContents() = - node { - Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "GetAssemblyData", nm) - return! self.GetAssemblyData(opts, userOpName + ".CheckReferencedProject(" + nm + ")") - } - - member x.TryGetLogicalTimeStamp(cache) = - self.TryGetLogicalTimeStampForProject(cache, opts) - - member x.FileName = nm - } - - | FSharpReferencedProject.PEReference(getStamp, delayedReader) -> - { new IProjectReference with - member x.EvaluateRawContents() = - node { - let! ilReaderOpt = delayedReader.TryGetILModuleReader() |> NodeCode.FromCancellable - - match ilReaderOpt with - | Some ilReader -> - let ilModuleDef, ilAsmRefs = ilReader.ILModuleDef, ilReader.ILAssemblyRefs - let data = RawFSharpAssemblyData(ilModuleDef, ilAsmRefs) :> IRawFSharpAssemblyData - return ProjectAssemblyDataResult.Available data - | _ -> - // Note 'false' - if a PEReference doesn't find an ILModuleReader then we don't - // continue to try to use an on-disk DLL - return ProjectAssemblyDataResult.Unavailable false - } - - member x.TryGetLogicalTimeStamp _ = getStamp () |> Some - member x.FileName = delayedReader.OutputFile - } - - | FSharpReferencedProject.ILModuleReference(nm, getStamp, getReader) -> - { new IProjectReference with - member x.EvaluateRawContents() = - cancellable { - let ilReader = getReader () - let ilModuleDef, ilAsmRefs = ilReader.ILModuleDef, ilReader.ILAssemblyRefs - let data = RawFSharpAssemblyData(ilModuleDef, ilAsmRefs) :> IRawFSharpAssemblyData - return ProjectAssemblyDataResult.Available data - } - |> NodeCode.FromCancellable - - member x.TryGetLogicalTimeStamp _ = getStamp () |> Some - member x.FileName = nm - } - ] - - /// CreateOneIncrementalBuilder (for background type checking). Note that fsc.fs also - /// creates an incremental builder used by the command line compiler. - let CreateOneIncrementalBuilder (options: FSharpProjectOptions, userOpName) = - node { - use _ = - Activity.start "BackgroundCompiler.CreateOneIncrementalBuilder" [| Activity.Tags.project, options.ProjectFileName |] - - Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "CreateOneIncrementalBuilder", options.ProjectFileName) - let projectReferences = getProjectReferences options userOpName - - let loadClosure = scriptClosureCache.TryGet(AnyCallerThread, options) - - let dependencyProvider = - if options.UseScriptResolutionRules then - Some dependencyProviderForScripts - else - None - - let! builderOpt, diagnostics = - IncrementalBuilder.TryCreateIncrementalBuilderForProjectOptions( - legacyReferenceResolver, - FSharpCheckerResultsSettings.defaultFSharpBinariesDir, - frameworkTcImportsCache, - loadClosure, - Array.toList options.SourceFiles, - Array.toList options.OtherOptions, - projectReferences, - options.ProjectDirectory, - options.UseScriptResolutionRules, - keepAssemblyContents, - keepAllBackgroundResolutions, - tryGetMetadataSnapshot, - suggestNamesForErrors, - keepAllBackgroundSymbolUses, - enableBackgroundItemKeyStoreAndSemanticClassification, - enablePartialTypeChecking, - dependencyProvider, - parallelReferenceResolution, - captureIdentifiersWhenParsing, - getSource, - useChangeNotifications, - useSyntaxTreeCache - ) - - match builderOpt with - | None -> () - | Some builder -> - -#if !NO_TYPEPROVIDERS - // Register the behaviour that responds to CCUs being invalidated because of type - // provider Invalidate events. This invalidates the configuration in the build. - builder.ImportsInvalidatedByTypeProvider.Add(fun () -> self.InvalidateConfiguration(options, userOpName)) -#endif - - // Register the callback called just before a file is typechecked by the background builder (without recording - // errors or intellisense information). - // - // This indicates to the UI that the file type check state is dirty. If the file is open and visible then - // the UI will sooner or later request a typecheck of the file, recording errors and intellisense information. - builder.BeforeFileChecked.Add(fun file -> beforeFileChecked.Trigger(file, options)) - builder.FileParsed.Add(fun file -> fileParsed.Trigger(file, options)) - builder.FileChecked.Add(fun file -> fileChecked.Trigger(file, options)) - builder.ProjectChecked.Add(fun () -> projectChecked.Trigger options) - - return (builderOpt, diagnostics) - } - - let parseCacheLock = Lock() - - // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.parseFileInProjectCache. Most recently used cache for parsing files. - let parseFileCache = - MruCache(parseFileCacheSize, areSimilar = AreSimilarForParsing, areSame = AreSameForParsing) - - // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.checkFileInProjectCache - // - /// Cache which holds recently seen type-checks. - /// This cache may hold out-of-date entries, in two senses - /// - there may be a more recent antecedent state available because the background build has made it available - /// - the source for the file may have changed - - // Also keyed on source. This can only be out of date if the antecedent is out of date - let checkFileInProjectCache = - MruCache>( - keepStrongly = checkFileInProjectCacheSize, - areSame = AreSameForChecking3, - areSimilar = AreSubsumable3 - ) - - // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.backgroundCompiler.incrementalBuildersCache. This root typically holds more - // live information than anything else in the F# Language Service, since it holds up to 3 (projectCacheStrongSize) background project builds - // strongly. - // - /// Cache of builds keyed by options. - let gate = obj () - - let incrementalBuildersCache = - MruCache>( - keepStrongly = projectCacheSize, - keepMax = projectCacheSize, - areSame = FSharpProjectOptions.AreSameForChecking, - areSimilar = FSharpProjectOptions.UseSameProject - ) - - let tryGetBuilderNode options = - incrementalBuildersCache.TryGet(AnyCallerThread, options) - - let tryGetBuilder options : NodeCode option = - tryGetBuilderNode options |> Option.map (fun x -> x.GetOrComputeValue()) - - let tryGetSimilarBuilder options : NodeCode option = - incrementalBuildersCache.TryGetSimilar(AnyCallerThread, options) - |> Option.map (fun x -> x.GetOrComputeValue()) - - let tryGetAnyBuilder options : NodeCode option = - incrementalBuildersCache.TryGetAny(AnyCallerThread, options) - |> Option.map (fun x -> x.GetOrComputeValue()) - - let createBuilderNode (options, userOpName, ct: CancellationToken) = - lock gate (fun () -> - if ct.IsCancellationRequested then - GraphNode.FromResult(None, [||]) - else - let getBuilderNode = GraphNode(CreateOneIncrementalBuilder(options, userOpName)) - incrementalBuildersCache.Set(AnyCallerThread, options, getBuilderNode) - getBuilderNode) - - let createAndGetBuilder (options, userOpName) = - node { - let! ct = NodeCode.CancellationToken - let getBuilderNode = createBuilderNode (options, userOpName, ct) - return! getBuilderNode.GetOrComputeValue() - } - - let getOrCreateBuilder (options, userOpName) : NodeCode = - match tryGetBuilder options with - | Some getBuilder -> - node { - match! getBuilder with - | builderOpt, creationDiags when builderOpt.IsNone || not builderOpt.Value.IsReferencesInvalidated -> return builderOpt, creationDiags - | _ -> - // The builder could be re-created, - // clear the check file caches that are associated with it. - // We must do this in order to not return stale results when references - // in the project get changed/added/removed. - parseCacheLock.AcquireLock(fun ltok -> - options.SourceFiles - |> Array.iter (fun sourceFile -> - let key = (sourceFile, 0L, options) - checkFileInProjectCache.RemoveAnySimilar(ltok, key))) - - return! createAndGetBuilder (options, userOpName) - } - | _ -> createAndGetBuilder (options, userOpName) - - let getSimilarOrCreateBuilder (options, userOpName) = - match tryGetSimilarBuilder options with - | Some res -> res - // The builder does not exist at all. Create it. - | None -> getOrCreateBuilder (options, userOpName) - - let getOrCreateBuilderWithInvalidationFlag (options, canInvalidateProject, userOpName) = - if canInvalidateProject then - getOrCreateBuilder (options, userOpName) - else - getSimilarOrCreateBuilder (options, userOpName) - - let getAnyBuilder (options, userOpName) = - match tryGetAnyBuilder options with - | Some getBuilder -> getBuilder - | _ -> getOrCreateBuilder (options, userOpName) - - static let mutable actualParseFileCount = 0 - - static let mutable actualCheckFileCount = 0 - - /// Should be a fast operation. Ensures that we have only one async lazy object per file and its hash. - let getCheckFileNode (parseResults, sourceText, fileName, options, _fileVersion, builder, tcPrior, tcInfo, creationDiags) = - - // Here we lock for the creation of the node, not its execution - parseCacheLock.AcquireLock(fun ltok -> - let key = (fileName, sourceText.GetHashCode() |> int64, options) - - match checkFileInProjectCache.TryGet(ltok, key) with - | Some res -> res - | _ -> - let res = - GraphNode( - node { - let! res = self.CheckOneFileImplAux(parseResults, sourceText, fileName, options, builder, tcPrior, tcInfo, creationDiags) - Interlocked.Increment(&actualCheckFileCount) |> ignore - return res - } - ) - - checkFileInProjectCache.Set(ltok, key, res) - res) - - member _.ParseFile(fileName: string, sourceText: ISourceText, options: FSharpParsingOptions, cache: bool, flatErrors: bool, userOpName: string) = - async { - use _ = - Activity.start - "BackgroundCompiler.ParseFile" - [| - Activity.Tags.fileName, fileName - Activity.Tags.userOpName, userOpName - Activity.Tags.cache, cache.ToString() - |] - - let! ct = Async.CancellationToken - use _ = Cancellable.UsingToken(ct) - - if cache then - let hash = sourceText.GetHashCode() |> int64 - - match parseCacheLock.AcquireLock(fun ltok -> parseFileCache.TryGet(ltok, (fileName, hash, options))) with - | Some res -> return res - | None -> - Interlocked.Increment(&actualParseFileCount) |> ignore - let! ct = Async.CancellationToken - - let parseDiagnostics, parseTree, anyErrors = - ParseAndCheckFile.parseFile ( - sourceText, - fileName, - options, - userOpName, - suggestNamesForErrors, - flatErrors, - captureIdentifiersWhenParsing, - ct - ) - - let res = FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, options.SourceFiles) - parseCacheLock.AcquireLock(fun ltok -> parseFileCache.Set(ltok, (fileName, hash, options), res)) - return res - else - let! ct = Async.CancellationToken - - let parseDiagnostics, parseTree, anyErrors = - ParseAndCheckFile.parseFile (sourceText, fileName, options, userOpName, false, flatErrors, captureIdentifiersWhenParsing, ct) - - return FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, options.SourceFiles) - } - - /// Fetch the parse information from the background compiler (which checks w.r.t. the FileSystem API) - member _.GetBackgroundParseResultsForFileInProject(fileName, options, userOpName) = - node { - use _ = - Activity.start - "BackgroundCompiler.GetBackgroundParseResultsForFileInProject" - [| Activity.Tags.fileName, fileName; Activity.Tags.userOpName, userOpName |] - - let! ct = NodeCode.CancellationToken - use _ = Cancellable.UsingToken(ct) - - let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName) - - match builderOpt with - | None -> - let parseTree = EmptyParsedInput(fileName, (false, false)) - return FSharpParseFileResults(creationDiags, parseTree, true, [||]) - | Some builder -> - let parseTree, _, _, parseDiagnostics = builder.GetParseResultsForFile fileName - - let parseDiagnostics = - DiagnosticHelpers.CreateDiagnostics( - builder.TcConfig.diagnosticsOptions, - false, - fileName, - parseDiagnostics, - suggestNamesForErrors, - builder.TcConfig.flatErrors, - None - ) - - let diagnostics = [| yield! creationDiags; yield! parseDiagnostics |] - - let parseResults = - FSharpParseFileResults( - diagnostics = diagnostics, - input = parseTree, - parseHadErrors = false, - dependencyFiles = builder.AllDependenciesDeprecated - ) - - return parseResults - } - - member _.GetCachedCheckFileResult(builder: IncrementalBuilder, fileName, sourceText: ISourceText, options) = - node { - use _ = - Activity.start "BackgroundCompiler.GetCachedCheckFileResult" [| Activity.Tags.fileName, fileName |] - - let hash = sourceText.GetHashCode() |> int64 - let key = (fileName, hash, options) - let cachedResultsOpt = parseCacheLock.AcquireLock(fun ltok -> checkFileInProjectCache.TryGet(ltok, key)) - - match cachedResultsOpt with - | Some cachedResults -> - match! cachedResults.GetOrComputeValue() with - | parseResults, checkResults, _, priorTimeStamp when - (match builder.GetCheckResultsBeforeFileInProjectEvenIfStale fileName with - | None -> false - | Some(tcPrior) -> - tcPrior.ProjectTimeStamp = priorTimeStamp - && builder.AreCheckResultsBeforeFileInProjectReady(fileName)) - -> - return Some(parseResults, checkResults) - | _ -> - parseCacheLock.AcquireLock(fun ltok -> checkFileInProjectCache.RemoveAnySimilar(ltok, key)) - return None - | _ -> return None - } - - member private _.CheckOneFileImplAux - ( - parseResults: FSharpParseFileResults, - sourceText: ISourceText, - fileName: string, - options: FSharpProjectOptions, - builder: IncrementalBuilder, - tcPrior: PartialCheckResults, - tcInfo: TcInfo, - creationDiags: FSharpDiagnostic[] - ) : NodeCode = - - node { - // Get additional script #load closure information if applicable. - // For scripts, this will have been recorded by GetProjectOptionsFromScript. - let tcConfig = tcPrior.TcConfig - let loadClosure = scriptClosureCache.TryGet(AnyCallerThread, options) - - let! checkAnswer = - FSharpCheckFileResults.CheckOneFile( - parseResults, - sourceText, - fileName, - options.ProjectFileName, - tcConfig, - tcPrior.TcGlobals, - tcPrior.TcImports, - tcInfo.tcState, - tcInfo.moduleNamesDict, - loadClosure, - tcInfo.TcDiagnostics, - options.IsIncompleteTypeCheckEnvironment, - options, - builder, - Array.ofList tcInfo.tcDependencyFiles, - creationDiags, - parseResults.Diagnostics, - keepAssemblyContents, - suggestNamesForErrors - ) - |> NodeCode.FromCancellable - - GraphNode.SetPreferredUILang tcConfig.preferredUiLang - return (parseResults, checkAnswer, sourceText.GetHashCode() |> int64, tcPrior.ProjectTimeStamp) - } - - member private bc.CheckOneFileImpl - ( - parseResults: FSharpParseFileResults, - sourceText: ISourceText, - fileName: string, - options: FSharpProjectOptions, - fileVersion: int, - builder: IncrementalBuilder, - tcPrior: PartialCheckResults, - tcInfo: TcInfo, - creationDiags: FSharpDiagnostic[] - ) = - - node { - match! bc.GetCachedCheckFileResult(builder, fileName, sourceText, options) with - | Some(_, results) -> return FSharpCheckFileAnswer.Succeeded results - | _ -> - let lazyCheckFile = - getCheckFileNode (parseResults, sourceText, fileName, options, fileVersion, builder, tcPrior, tcInfo, creationDiags) - - let! _, results, _, _ = lazyCheckFile.GetOrComputeValue() - return FSharpCheckFileAnswer.Succeeded results - } - - /// Type-check the result obtained by parsing, but only if the antecedent type checking context is available. - member bc.CheckFileInProjectAllowingStaleCachedResults - ( - parseResults: FSharpParseFileResults, - fileName, - fileVersion, - sourceText: ISourceText, - options, - userOpName - ) = - node { - use _ = - Activity.start - "BackgroundCompiler.CheckFileInProjectAllowingStaleCachedResults" - [| - Activity.Tags.project, options.ProjectFileName - Activity.Tags.fileName, fileName - Activity.Tags.userOpName, userOpName - |] - - let! ct = NodeCode.CancellationToken - use _ = Cancellable.UsingToken(ct) - - let! cachedResults = - node { - let! builderOpt, creationDiags = getAnyBuilder (options, userOpName) - - match builderOpt with - | Some builder -> - match! bc.GetCachedCheckFileResult(builder, fileName, sourceText, options) with - | Some(_, checkResults) -> return Some(builder, creationDiags, Some(FSharpCheckFileAnswer.Succeeded checkResults)) - | _ -> return Some(builder, creationDiags, None) - | _ -> return None // the builder wasn't ready - } - - match cachedResults with - | None -> return None - | Some(_, _, Some x) -> return Some x - | Some(builder, creationDiags, None) -> - Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "CheckFileInProjectAllowingStaleCachedResults.CacheMiss", fileName) - - match builder.GetCheckResultsBeforeFileInProjectEvenIfStale fileName with - | Some tcPrior -> - match tcPrior.TryPeekTcInfo() with - | Some tcInfo -> - let! checkResults = - bc.CheckOneFileImpl(parseResults, sourceText, fileName, options, fileVersion, builder, tcPrior, tcInfo, creationDiags) - - return Some checkResults - | None -> return None - | None -> return None // the incremental builder was not up to date - } - - /// Type-check the result obtained by parsing. Force the evaluation of the antecedent type checking context if needed. - member bc.CheckFileInProject(parseResults: FSharpParseFileResults, fileName, fileVersion, sourceText: ISourceText, options, userOpName) = - node { - use _ = - Activity.start - "BackgroundCompiler.CheckFileInProject" - [| - Activity.Tags.project, options.ProjectFileName - Activity.Tags.fileName, fileName - Activity.Tags.userOpName, userOpName - |] - - let! ct = NodeCode.CancellationToken - use _ = Cancellable.UsingToken(ct) - - let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName) - - match builderOpt with - | None -> return FSharpCheckFileAnswer.Succeeded(FSharpCheckFileResults.MakeEmpty(fileName, creationDiags, keepAssemblyContents)) - | Some builder -> - // Check the cache. We can only use cached results when there is no work to do to bring the background builder up-to-date - let! cachedResults = bc.GetCachedCheckFileResult(builder, fileName, sourceText, options) - - match cachedResults with - | Some(_, checkResults) -> return FSharpCheckFileAnswer.Succeeded checkResults - | _ -> - let! tcPrior = builder.GetCheckResultsBeforeFileInProject fileName - let! tcInfo = tcPrior.GetOrComputeTcInfo() - return! bc.CheckOneFileImpl(parseResults, sourceText, fileName, options, fileVersion, builder, tcPrior, tcInfo, creationDiags) - } - - /// Parses and checks the source file and returns untyped AST and check results. - member bc.ParseAndCheckFileInProject(fileName: string, fileVersion, sourceText: ISourceText, options: FSharpProjectOptions, userOpName) = - node { - use _ = - Activity.start - "BackgroundCompiler.ParseAndCheckFileInProject" - [| - Activity.Tags.project, options.ProjectFileName - Activity.Tags.fileName, fileName - Activity.Tags.userOpName, userOpName - |] - - let! ct = NodeCode.CancellationToken - use _ = Cancellable.UsingToken(ct) - - let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName) - - match builderOpt with - | None -> - let parseTree = EmptyParsedInput(fileName, (false, false)) - let parseResults = FSharpParseFileResults(creationDiags, parseTree, true, [||]) - return (parseResults, FSharpCheckFileAnswer.Aborted) - - | Some builder -> - let! cachedResults = bc.GetCachedCheckFileResult(builder, fileName, sourceText, options) - - match cachedResults with - | Some(parseResults, checkResults) -> return (parseResults, FSharpCheckFileAnswer.Succeeded checkResults) - | _ -> - let! tcPrior = builder.GetCheckResultsBeforeFileInProject fileName - let! tcInfo = tcPrior.GetOrComputeTcInfo() - // Do the parsing. - let parsingOptions = - FSharpParsingOptions.FromTcConfig(builder.TcConfig, Array.ofList builder.SourceFiles, options.UseScriptResolutionRules) - - GraphNode.SetPreferredUILang tcPrior.TcConfig.preferredUiLang - let! ct = NodeCode.CancellationToken - - let parseDiagnostics, parseTree, anyErrors = - ParseAndCheckFile.parseFile ( - sourceText, - fileName, - parsingOptions, - userOpName, - suggestNamesForErrors, - builder.TcConfig.flatErrors, - captureIdentifiersWhenParsing, - ct - ) - - let parseResults = - FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, builder.AllDependenciesDeprecated) - - let! checkResults = - bc.CheckOneFileImpl(parseResults, sourceText, fileName, options, fileVersion, builder, tcPrior, tcInfo, creationDiags) - - return (parseResults, checkResults) - } - - member _.NotifyFileChanged(fileName, options, userOpName) = - node { - use _ = - Activity.start - "BackgroundCompiler.NotifyFileChanged" - [| - Activity.Tags.project, options.ProjectFileName - Activity.Tags.fileName, fileName - Activity.Tags.userOpName, userOpName - |] - - let! ct = NodeCode.CancellationToken - use _ = Cancellable.UsingToken(ct) - - let! builderOpt, _ = getOrCreateBuilder (options, userOpName) - - match builderOpt with - | None -> return () - | Some builder -> do! builder.NotifyFileChanged(fileName, DateTime.UtcNow) - } - - /// Fetch the check information from the background compiler (which checks w.r.t. the FileSystem API) - member _.GetBackgroundCheckResultsForFileInProject(fileName, options, userOpName) = - node { - use _ = - Activity.start - "BackgroundCompiler.ParseAndCheckFileInProject" - [| - Activity.Tags.project, options.ProjectFileName - Activity.Tags.fileName, fileName - Activity.Tags.userOpName, userOpName - |] - - let! ct = NodeCode.CancellationToken - use _ = Cancellable.UsingToken(ct) - - let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName) - - match builderOpt with - | None -> - let parseTree = EmptyParsedInput(fileName, (false, false)) - let parseResults = FSharpParseFileResults(creationDiags, parseTree, true, [||]) - let typedResults = FSharpCheckFileResults.MakeEmpty(fileName, creationDiags, true) - return (parseResults, typedResults) - | Some builder -> - let parseTree, _, _, parseDiagnostics = builder.GetParseResultsForFile fileName - let! tcProj = builder.GetFullCheckResultsAfterFileInProject fileName - - let! tcInfo, tcInfoExtras = tcProj.GetOrComputeTcInfoWithExtras() - - let tcResolutions = tcInfoExtras.tcResolutions - let tcSymbolUses = tcInfoExtras.tcSymbolUses - let tcOpenDeclarations = tcInfoExtras.tcOpenDeclarations - let latestCcuSigForFile = tcInfo.latestCcuSigForFile - let tcState = tcInfo.tcState - let tcEnvAtEnd = tcInfo.tcEnvAtEndOfFile - let latestImplementationFile = tcInfoExtras.latestImplFile - let tcDependencyFiles = tcInfo.tcDependencyFiles - let tcDiagnostics = tcInfo.TcDiagnostics - let diagnosticsOptions = builder.TcConfig.diagnosticsOptions - - let symbolEnv = - SymbolEnv(tcProj.TcGlobals, tcInfo.tcState.Ccu, Some tcInfo.tcState.CcuSig, tcProj.TcImports) - |> Some - - let parseDiagnostics = - DiagnosticHelpers.CreateDiagnostics( - diagnosticsOptions, - false, - fileName, - parseDiagnostics, - suggestNamesForErrors, - builder.TcConfig.flatErrors, - None - ) - - let parseDiagnostics = [| yield! creationDiags; yield! parseDiagnostics |] - - let tcDiagnostics = - DiagnosticHelpers.CreateDiagnostics( - diagnosticsOptions, - false, - fileName, - tcDiagnostics, - suggestNamesForErrors, - builder.TcConfig.flatErrors, - symbolEnv - ) - - let tcDiagnostics = [| yield! creationDiags; yield! tcDiagnostics |] - - let parseResults = - FSharpParseFileResults( - diagnostics = parseDiagnostics, - input = parseTree, - parseHadErrors = false, - dependencyFiles = builder.AllDependenciesDeprecated - ) - - let loadClosure = scriptClosureCache.TryGet(AnyCallerThread, options) - - let typedResults = - FSharpCheckFileResults.Make( - fileName, - options.ProjectFileName, - tcProj.TcConfig, - tcProj.TcGlobals, - options.IsIncompleteTypeCheckEnvironment, - builder, - options, - Array.ofList tcDependencyFiles, - creationDiags, - parseResults.Diagnostics, - tcDiagnostics, - keepAssemblyContents, - Option.get latestCcuSigForFile, - tcState.Ccu, - tcProj.TcImports, - tcEnvAtEnd.AccessRights, - tcResolutions, - tcSymbolUses, - tcEnvAtEnd.NameEnv, - loadClosure, - latestImplementationFile, - tcOpenDeclarations - ) - - return (parseResults, typedResults) - } - - member _.FindReferencesInFile - ( - fileName: string, - options: FSharpProjectOptions, - symbol: FSharpSymbol, - canInvalidateProject: bool, - userOpName: string - ) = - node { - use _ = - Activity.start - "BackgroundCompiler.FindReferencesInFile" - [| - Activity.Tags.project, options.ProjectFileName - Activity.Tags.fileName, fileName - Activity.Tags.userOpName, userOpName - "symbol", symbol.FullName - |] - - let! builderOpt, _ = getOrCreateBuilderWithInvalidationFlag (options, canInvalidateProject, userOpName) - - match builderOpt with - | None -> return Seq.empty - | Some builder -> - if builder.ContainsFile fileName then - let! checkResults = builder.GetFullCheckResultsAfterFileInProject fileName - let! keyStoreOpt = checkResults.GetOrComputeItemKeyStoreIfEnabled() - - match keyStoreOpt with - | None -> return Seq.empty - | Some reader -> return reader.FindAll symbol.Item - else - return Seq.empty - } - - member _.GetSemanticClassificationForFile(fileName: string, options: FSharpProjectOptions, userOpName: string) = - node { - use _ = - Activity.start - "BackgroundCompiler.GetSemanticClassificationForFile" - [| - Activity.Tags.project, options.ProjectFileName - Activity.Tags.fileName, fileName - Activity.Tags.userOpName, userOpName - |] - - let! ct = NodeCode.CancellationToken - use _ = Cancellable.UsingToken(ct) - - let! builderOpt, _ = getOrCreateBuilder (options, userOpName) - - match builderOpt with - | None -> return None - | Some builder -> - let! checkResults = builder.GetFullCheckResultsAfterFileInProject fileName - let! scopt = checkResults.GetOrComputeSemanticClassificationIfEnabled() - - match scopt with - | None -> return None - | Some sc -> return Some(sc.GetView()) - } - - /// Try to get recent approximate type check results for a file. - member _.TryGetRecentCheckResultsForFile(fileName: string, options: FSharpProjectOptions, sourceText: ISourceText option, _userOpName: string) = - use _ = - Activity.start - "BackgroundCompiler.GetSemanticClassificationForFile" - [| - Activity.Tags.project, options.ProjectFileName - Activity.Tags.fileName, fileName - Activity.Tags.userOpName, _userOpName - |] - - match sourceText with - | Some sourceText -> - let hash = sourceText.GetHashCode() |> int64 - - let resOpt = - parseCacheLock.AcquireLock(fun ltok -> checkFileInProjectCache.TryGet(ltok, (fileName, hash, options))) - - match resOpt with - | Some res -> - match res.TryPeekValue() with - | ValueSome(a, b, c, _) -> Some(a, b, c) - | ValueNone -> None - | None -> None - | None -> None - - /// Parse and typecheck the whole project (the implementation, called recursively as project graph is evaluated) - member private _.ParseAndCheckProjectImpl(options, userOpName) = - node { - let! ct = NodeCode.CancellationToken - use _ = Cancellable.UsingToken(ct) - - let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName) - - match builderOpt with - | None -> - let emptyResults = - FSharpCheckProjectResults(options.ProjectFileName, None, keepAssemblyContents, creationDiags, None) - - return emptyResults - | Some builder -> - let! tcProj, ilAssemRef, tcAssemblyDataOpt, tcAssemblyExprOpt = builder.GetFullCheckResultsAndImplementationsForProject() - let diagnosticsOptions = tcProj.TcConfig.diagnosticsOptions - let fileName = DummyFileNameForRangesWithoutASpecificLocation - - // Although we do not use 'tcInfoExtras', computing it will make sure we get an extra info. - let! tcInfo, _tcInfoExtras = tcProj.GetOrComputeTcInfoWithExtras() - - let topAttribs = tcInfo.topAttribs - let tcState = tcInfo.tcState - let tcEnvAtEnd = tcInfo.tcEnvAtEndOfFile - let tcDiagnostics = tcInfo.TcDiagnostics - let tcDependencyFiles = tcInfo.tcDependencyFiles - - let symbolEnv = - SymbolEnv(tcProj.TcGlobals, tcInfo.tcState.Ccu, Some tcInfo.tcState.CcuSig, tcProj.TcImports) - |> Some - - let tcDiagnostics = - DiagnosticHelpers.CreateDiagnostics( - diagnosticsOptions, - true, - fileName, - tcDiagnostics, - suggestNamesForErrors, - builder.TcConfig.flatErrors, - symbolEnv - ) - - let diagnostics = [| yield! creationDiags; yield! tcDiagnostics |] - - let getAssemblyData () = - match tcAssemblyDataOpt with - | ProjectAssemblyDataResult.Available data -> Some data - | _ -> None - - let details = - (tcProj.TcGlobals, - tcProj.TcImports, - tcState.Ccu, - tcState.CcuSig, - Choice1Of2 builder, - topAttribs, - getAssemblyData, - ilAssemRef, - tcEnvAtEnd.AccessRights, - tcAssemblyExprOpt, - Array.ofList tcDependencyFiles, - options) - - let results = - FSharpCheckProjectResults(options.ProjectFileName, Some tcProj.TcConfig, keepAssemblyContents, diagnostics, Some details) - - return results - } - - member _.GetAssemblyData(options, userOpName) = - node { - use _ = - Activity.start - "BackgroundCompiler.GetAssemblyData" - [| - Activity.Tags.project, options.ProjectFileName - Activity.Tags.userOpName, userOpName - |] - - let! builderOpt, _ = getOrCreateBuilder (options, userOpName) - - match builderOpt with - | None -> return ProjectAssemblyDataResult.Unavailable true - | Some builder -> - let! _, _, tcAssemblyDataOpt, _ = builder.GetCheckResultsAndImplementationsForProject() - return tcAssemblyDataOpt - } - - /// Get the timestamp that would be on the output if fully built immediately - member private _.TryGetLogicalTimeStampForProject(cache, options) = - match tryGetBuilderNode options with - | Some lazyWork -> - match lazyWork.TryPeekValue() with - | ValueSome(Some builder, _) -> Some(builder.GetLogicalTimeStampForProject(cache)) - | _ -> None - | _ -> None - - /// Parse and typecheck the whole project. - member bc.ParseAndCheckProject(options, userOpName) = - use _ = - Activity.start - "BackgroundCompiler.ParseAndCheckProject" - [| - Activity.Tags.project, options.ProjectFileName - Activity.Tags.userOpName, userOpName - |] - - bc.ParseAndCheckProjectImpl(options, userOpName) - - member _.GetProjectOptionsFromScript - ( - fileName, - sourceText, - previewEnabled, - loadedTimeStamp, - otherFlags, - useFsiAuxLib: bool option, - useSdkRefs: bool option, - sdkDirOverride: string option, - assumeDotNetFramework: bool option, - optionsStamp: int64 option, - _userOpName - ) = - use _ = - Activity.start - "BackgroundCompiler.GetProjectOptionsFromScript" - [| Activity.Tags.fileName, fileName; Activity.Tags.userOpName, _userOpName |] - - cancellable { - // Do we add a reference to FSharp.Compiler.Interactive.Settings by default? - let useFsiAuxLib = defaultArg useFsiAuxLib true - let useSdkRefs = defaultArg useSdkRefs true - let reduceMemoryUsage = ReduceMemoryFlag.Yes - let previewEnabled = defaultArg previewEnabled false - - // Do we assume .NET Framework references for scripts? - let assumeDotNetFramework = defaultArg assumeDotNetFramework true - - let! ct = Cancellable.token () - use _ = Cancellable.UsingToken(ct) - - let extraFlags = - if previewEnabled then - [| "--langversion:preview" |] - else - [||] - - let otherFlags = defaultArg otherFlags extraFlags - - use diagnostics = new DiagnosticsScope(otherFlags |> Array.contains "--flaterrors") - - let useSimpleResolution = otherFlags |> Array.exists (fun x -> x = "--simpleresolution") - - let loadedTimeStamp = defaultArg loadedTimeStamp DateTime.MaxValue // Not 'now', we don't want to force reloading - - let applyCompilerOptions tcConfigB = - let fsiCompilerOptions = GetCoreFsiCompilerOptions tcConfigB - ParseCompilerOptions(ignore, fsiCompilerOptions, Array.toList otherFlags) - - let loadClosure = - LoadClosure.ComputeClosureOfScriptText( - legacyReferenceResolver, - FSharpCheckerResultsSettings.defaultFSharpBinariesDir, - fileName, - sourceText, - CodeContext.Editing, - useSimpleResolution, - useFsiAuxLib, - useSdkRefs, - sdkDirOverride, - Lexhelp.LexResourceManager(), - applyCompilerOptions, - assumeDotNetFramework, - tryGetMetadataSnapshot, - reduceMemoryUsage, - dependencyProviderForScripts - ) - - let otherFlags = - [| - yield "--noframework" - yield "--warn:3" - yield! otherFlags - for r in loadClosure.References do - yield "-r:" + fst r - for code, _ in loadClosure.NoWarns do - yield "--nowarn:" + code - |] - - let options = - { - ProjectFileName = fileName + ".fsproj" // Make a name that is unique in this directory. - ProjectId = None - SourceFiles = loadClosure.SourceFiles |> List.map fst |> List.toArray - OtherOptions = otherFlags - ReferencedProjects = [||] - IsIncompleteTypeCheckEnvironment = false - UseScriptResolutionRules = true - LoadTime = loadedTimeStamp - UnresolvedReferences = Some(FSharpUnresolvedReferencesSet(loadClosure.UnresolvedReferences)) - OriginalLoadReferences = loadClosure.OriginalLoadReferences - Stamp = optionsStamp - } - - scriptClosureCache.Set(AnyCallerThread, options, loadClosure) // Save the full load closure for later correlation. - - let diags = - loadClosure.LoadClosureRootFileDiagnostics - |> List.map (fun (exn, isError) -> - FSharpDiagnostic.CreateFromException( - exn, - isError, - range.Zero, - false, - options.OtherOptions |> Array.contains "--flaterrors", - None - )) - - return options, (diags @ diagnostics.Diagnostics) - } - |> Cancellable.toAsync - - member bc.InvalidateConfiguration(options: FSharpProjectOptions, userOpName) = - use _ = - Activity.start - "BackgroundCompiler.InvalidateConfiguration" - [| - Activity.Tags.project, options.ProjectFileName - Activity.Tags.userOpName, userOpName - |] - - if incrementalBuildersCache.ContainsSimilarKey(AnyCallerThread, options) then - parseCacheLock.AcquireLock(fun ltok -> - for sourceFile in options.SourceFiles do - checkFileInProjectCache.RemoveAnySimilar(ltok, (sourceFile, 0L, options))) - - let _ = createBuilderNode (options, userOpName, CancellationToken.None) - () - - member bc.ClearCache(options: seq, _userOpName) = - use _ = Activity.start "BackgroundCompiler.ClearCache" [| Activity.Tags.userOpName, _userOpName |] - - lock gate (fun () -> - options - |> Seq.iter (fun options -> - incrementalBuildersCache.RemoveAnySimilar(AnyCallerThread, options) - - parseCacheLock.AcquireLock(fun ltok -> - for sourceFile in options.SourceFiles do - checkFileInProjectCache.RemoveAnySimilar(ltok, (sourceFile, 0L, options))))) - - member _.NotifyProjectCleaned(options: FSharpProjectOptions, userOpName) = - use _ = - Activity.start - "BackgroundCompiler.NotifyProjectCleaned" - [| - Activity.Tags.project, options.ProjectFileName - Activity.Tags.userOpName, userOpName - |] - - async { - let! ct = Async.CancellationToken - use _ = Cancellable.UsingToken(ct) - - let! ct = Async.CancellationToken - // If there was a similar entry (as there normally will have been) then re-establish an empty builder . This - // is a somewhat arbitrary choice - it will have the effect of releasing memory associated with the previous - // builder, but costs some time. - if incrementalBuildersCache.ContainsSimilarKey(AnyCallerThread, options) then - let _ = createBuilderNode (options, userOpName, ct) - () - } - - member _.BeforeBackgroundFileCheck = beforeFileChecked.Publish - - member _.FileParsed = fileParsed.Publish - - member _.FileChecked = fileChecked.Publish - - member _.ProjectChecked = projectChecked.Publish - - member _.ClearCaches() = - use _ = Activity.startNoTags "BackgroundCompiler.ClearCaches" - - lock gate (fun () -> - parseCacheLock.AcquireLock(fun ltok -> - checkFileInProjectCache.Clear(ltok) - parseFileCache.Clear(ltok)) - - incrementalBuildersCache.Clear(AnyCallerThread) - frameworkTcImportsCache.Clear() - scriptClosureCache.Clear AnyCallerThread) - - member _.DownsizeCaches() = - use _ = Activity.startNoTags "BackgroundCompiler.DownsizeCaches" - - lock gate (fun () -> - parseCacheLock.AcquireLock(fun ltok -> - checkFileInProjectCache.Resize(ltok, newKeepStrongly = 1) - parseFileCache.Resize(ltok, newKeepStrongly = 1)) - - incrementalBuildersCache.Resize(AnyCallerThread, newKeepStrongly = 1, newKeepMax = 1) - frameworkTcImportsCache.Downsize() - scriptClosureCache.Resize(AnyCallerThread, newKeepStrongly = 1, newKeepMax = 1)) - - member _.FrameworkImportsCache = frameworkTcImportsCache - - static member ActualParseFileCount = actualParseFileCount - - static member ActualCheckFileCount = actualCheckFileCount - [] // There is typically only one instance of this type in an IDE process. type FSharpChecker @@ -1366,26 +130,47 @@ type FSharpChecker captureIdentifiersWhenParsing, getSource, useChangeNotifications, - useSyntaxTreeCache + useSyntaxTreeCache, + useTransparentCompiler ) = let backgroundCompiler = - BackgroundCompiler( - legacyReferenceResolver, - projectCacheSize, - keepAssemblyContents, - keepAllBackgroundResolutions, - tryGetMetadataSnapshot, - suggestNamesForErrors, - keepAllBackgroundSymbolUses, - enableBackgroundItemKeyStoreAndSemanticClassification, - enablePartialTypeChecking, - parallelReferenceResolution, - captureIdentifiersWhenParsing, - getSource, - useChangeNotifications, - useSyntaxTreeCache - ) + if useTransparentCompiler = Some true then + TransparentCompiler( + legacyReferenceResolver, + projectCacheSize, + keepAssemblyContents, + keepAllBackgroundResolutions, + tryGetMetadataSnapshot, + suggestNamesForErrors, + keepAllBackgroundSymbolUses, + enableBackgroundItemKeyStoreAndSemanticClassification, + enablePartialTypeChecking, + parallelReferenceResolution, + captureIdentifiersWhenParsing, + getSource, + useChangeNotifications, + useSyntaxTreeCache + ) + :> IBackgroundCompiler + else + BackgroundCompiler( + legacyReferenceResolver, + projectCacheSize, + keepAssemblyContents, + keepAllBackgroundResolutions, + tryGetMetadataSnapshot, + suggestNamesForErrors, + keepAllBackgroundSymbolUses, + enableBackgroundItemKeyStoreAndSemanticClassification, + enablePartialTypeChecking, + parallelReferenceResolution, + captureIdentifiersWhenParsing, + getSource, + useChangeNotifications, + useSyntaxTreeCache + ) + :> IBackgroundCompiler static let globalInstance = lazy FSharpChecker.Create() @@ -1429,7 +214,8 @@ type FSharpChecker ?parallelReferenceResolution: bool, ?captureIdentifiersWhenParsing: bool, ?documentSource: DocumentSource, - ?useSyntaxTreeCache: bool + ?useSyntaxTreeCache: bool, + ?useTransparentCompiler: bool ) = use _ = Activity.startNoTags "FSharpChecker.Create" @@ -1480,9 +266,19 @@ type FSharpChecker | Some(DocumentSource.Custom f) -> Some f | _ -> None), useChangeNotifications, - useSyntaxTreeCache + useSyntaxTreeCache, + useTransparentCompiler ) + member _.UsesTransparentCompiler = useTransparentCompiler = Some true + + member _.TransparentCompiler = + match useTransparentCompiler with + | Some true -> backgroundCompiler :?> TransparentCompiler + | _ -> failwith "Transparent Compiler is not enabled." + + member this.Caches = this.TransparentCompiler.Caches + member _.ReferenceResolver = legacyReferenceResolver member _.MatchBraces(fileName, sourceText: ISourceText, options: FSharpParsingOptions, ?userOpName: string) = @@ -1521,6 +317,11 @@ type FSharpChecker let userOpName = defaultArg userOpName "Unknown" backgroundCompiler.ParseFile(fileName, sourceText, options, cache, false, userOpName) + member _.ParseFile(fileName, projectSnapshot, ?userOpName) = + let userOpName = defaultArg userOpName "Unknown" + + backgroundCompiler.ParseFile(fileName, projectSnapshot, userOpName) + member ic.ParseFileInProject(fileName, source: string, options, ?cache: bool, ?userOpName: string) = let parsingOptions, _ = ic.GetParsingOptionsFromProjectOptions(options) ic.ParseFile(fileName, SourceText.ofString source, parsingOptions, ?cache = cache, ?userOpName = userOpName) @@ -1547,9 +348,6 @@ type FSharpChecker use _ = Activity.start "FSharpChecker.Compile" [| Activity.Tags.userOpName, _userOpName |] async { - let! ct = Async.CancellationToken - use _ = Cancellable.UsingToken(ct) - let ctok = CompilationThreadToken() return CompileHelpers.compileFromArgs (ctok, argv, legacyReferenceResolver, None, None) } @@ -1564,7 +362,6 @@ type FSharpChecker backgroundCompiler.ClearCaches() ClearAllILModuleReaderCache() - // This is for unit testing only member ic.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients() = use _ = Activity.startNoTags "FsharpChecker.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients" @@ -1585,6 +382,10 @@ type FSharpChecker let userOpName = defaultArg userOpName "Unknown" backgroundCompiler.ClearCache(options, userOpName) + member _.ClearCache(projects: ProjectSnapshot.FSharpProjectIdentifier seq, ?userOpName: string) = + let userOpName = defaultArg userOpName "Unknown" + backgroundCompiler.ClearCache(projects, userOpName) + /// This function is called when a project has been cleaned, and thus type providers should be refreshed. member _.NotifyProjectCleaned(options: FSharpProjectOptions, ?userOpName: string) = let userOpName = defaultArg userOpName "Unknown" @@ -1650,12 +451,24 @@ type FSharpChecker backgroundCompiler.ParseAndCheckFileInProject(fileName, fileVersion, sourceText, options, userOpName) |> Async.AwaitNodeCode - member _.ParseAndCheckProject(options, ?userOpName: string) = + member _.ParseAndCheckFileInProject(fileName: string, projectSnapshot: FSharpProjectSnapshot, ?userOpName: string) = + let userOpName = defaultArg userOpName "Unknown" + + backgroundCompiler.ParseAndCheckFileInProject(fileName, projectSnapshot, userOpName) + |> Async.AwaitNodeCode + + member _.ParseAndCheckProject(options: FSharpProjectOptions, ?userOpName: string) = let userOpName = defaultArg userOpName "Unknown" backgroundCompiler.ParseAndCheckProject(options, userOpName) |> Async.AwaitNodeCode + member _.ParseAndCheckProject(projectSnapshot: FSharpProjectSnapshot, ?userOpName: string) = + let userOpName = defaultArg userOpName "Unknown" + + backgroundCompiler.ParseAndCheckProject(projectSnapshot, userOpName) + |> Async.AwaitNodeCode + member _.FindBackgroundReferencesInFile ( fileName: string, @@ -1669,9 +482,6 @@ type FSharpChecker let userOpName = defaultArg userOpName "Unknown" node { - let! ct = NodeCode.CancellationToken - use _ = Cancellable.UsingToken(ct) - if fastCheck <> Some true || not captureIdentifiersWhenParsing then return! backgroundCompiler.FindReferencesInFile(fileName, options, symbol, canInvalidateProject, userOpName) else @@ -1687,12 +497,36 @@ type FSharpChecker } |> Async.AwaitNodeCode + member _.FindBackgroundReferencesInFile(fileName: string, projectSnapshot: FSharpProjectSnapshot, symbol: FSharpSymbol, ?userOpName: string) = + let userOpName = defaultArg userOpName "Unknown" + + node { + let! parseResults = + backgroundCompiler.ParseFile(fileName, projectSnapshot, userOpName) + |> NodeCode.AwaitAsync + + if + parseResults.ParseTree.Identifiers |> Set.contains symbol.DisplayNameCore + || parseResults.ParseTree.Identifiers |> NamesContainAttribute symbol + then + return! backgroundCompiler.FindReferencesInFile(fileName, projectSnapshot, symbol, userOpName) + else + return Seq.empty + } + |> Async.AwaitNodeCode + member _.GetBackgroundSemanticClassificationForFile(fileName: string, options: FSharpProjectOptions, ?userOpName) = let userOpName = defaultArg userOpName "Unknown" backgroundCompiler.GetSemanticClassificationForFile(fileName, options, userOpName) |> Async.AwaitNodeCode + member _.GetBackgroundSemanticClassificationForFile(fileName: string, snapshot: FSharpProjectSnapshot, ?userOpName) = + let userOpName = defaultArg userOpName "Unknown" + + backgroundCompiler.GetSemanticClassificationForFile(fileName, snapshot, userOpName) + |> Async.AwaitNodeCode + /// For a given script file, get the ProjectOptions implied by the #load closure member _.GetProjectOptionsFromScript ( diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi index 297d7b367bc..14124fbda6b 100644 --- a/src/Compiler/Service/service.fsi +++ b/src/Compiler/Service/service.fsi @@ -6,8 +6,11 @@ namespace FSharp.Compiler.CodeAnalysis open System open System.IO +open System.Threading +open System.Threading.Tasks open FSharp.Compiler.AbstractIL.ILBinaryReader open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.CodeAnalysis.TransparentCompiler open FSharp.Compiler.CompilerConfig open FSharp.Compiler.Diagnostics open FSharp.Compiler.EditorServices @@ -42,6 +45,7 @@ type public FSharpChecker = /// When set to true we create a set of all identifiers for each parsed file which can be used to speed up finding references. /// Default: FileSystem. You can use Custom source to provide a function that will return the source for a given file path instead of reading it from the file system. Note that with this option the FSharpChecker will also not monitor the file system for file changes. It will expect to be notified of changes via the NotifyFileChanged method. /// Default: true. Indicates whether to keep parsing results in a cache. + /// Default: false. Indicates whether we use a new experimental background compiler. This does not yet support all features static member Create: ?projectCacheSize: int * ?keepAssemblyContents: bool * @@ -57,9 +61,13 @@ type public FSharpChecker = [] ?documentSource: DocumentSource * [] ?useSyntaxTreeCache: + bool * + [] ?useTransparentCompiler: bool -> FSharpChecker + member internal UsesTransparentCompiler: bool + /// /// Parse a source code file, returning information about brace matching in the file. /// Return an enumeration of the matching parenthetical tokens in the file. @@ -100,6 +108,10 @@ type public FSharpChecker = fileName: string * sourceText: ISourceText * options: FSharpParsingOptions * ?cache: bool * ?userOpName: string -> Async + [] + member ParseFile: + fileName: string * projectSnapshot: FSharpProjectSnapshot * ?userOpName: string -> Async + /// /// Parses a source code for a file. Returns an AST that can be traversed for various features. /// @@ -193,6 +205,11 @@ type public FSharpChecker = ?userOpName: string -> Async + [] + member ParseAndCheckFileInProject: + fileName: string * projectSnapshot: FSharpProjectSnapshot * ?userOpName: string -> + Async + /// /// Parse and typecheck all files in a project. /// All files are read from the FileSystem API @@ -203,6 +220,10 @@ type public FSharpChecker = /// An optional string used for tracing compiler operations associated with this request. member ParseAndCheckProject: options: FSharpProjectOptions * ?userOpName: string -> Async + [] + member ParseAndCheckProject: + projectSnapshot: FSharpProjectSnapshot * ?userOpName: string -> Async + /// /// For a given script file, get the FSharpProjectOptions implied by the #load closure. /// All files are read from the FileSystem API, except the file being checked. @@ -323,6 +344,11 @@ type public FSharpChecker = ?userOpName: string -> Async + [] + member FindBackgroundReferencesInFile: + fileName: string * projectSnapshot: FSharpProjectSnapshot * symbol: FSharpSymbol * ?userOpName: string -> + Async + /// /// Get semantic classification for a file. /// All files are read from the FileSystem API, including the file being checked. @@ -336,6 +362,18 @@ type public FSharpChecker = fileName: string * options: FSharpProjectOptions * ?userOpName: string -> Async + /// + /// Get semantic classification for a file. + /// + /// + /// The file name for the file. + /// The project snapshot for which we want to get the semantic classification. + /// An optional string used for tracing compiler operations associated with this request. + [] + member GetBackgroundSemanticClassificationForFile: + fileName: string * snapshot: FSharpProjectSnapshot * ?userOpName: string -> + Async + /// /// Compile using the given flags. Source files names are resolved via the FileSystem API. /// The output file must be given by a -o flag. @@ -377,6 +415,8 @@ type public FSharpChecker = /// An optional string used for tracing compiler operations associated with this request. member ClearCache: options: FSharpProjectOptions seq * ?userOpName: string -> unit + member ClearCache: projects: ProjectSnapshot.FSharpProjectIdentifier seq * ?userOpName: string -> unit + /// Report a statistic for testability static member ActualParseFileCount: int @@ -421,6 +461,10 @@ type public FSharpChecker = /// The event may be raised on a background thread. member ProjectChecked: IEvent + member internal TransparentCompiler: TransparentCompiler + + member internal Caches: CompilerCaches + [] static member Instance: FSharpChecker diff --git a/src/Compiler/Symbols/Exprs.fs b/src/Compiler/Symbols/Exprs.fs index 5ad053b2d9f..dfdfb782e46 100644 --- a/src/Compiler/Symbols/Exprs.fs +++ b/src/Compiler/Symbols/Exprs.fs @@ -899,12 +899,12 @@ module FSharpExprConvert = let typR = ConvType cenv (mkAppTy tycr tyargs) E.UnionCaseTag(ConvExpr cenv env arg1, typR) - | TOp.TraitCall (TTrait(tys, nm, memFlags, argTys, _retTy, _solution)), _, _ -> - let tysR = ConvTypes cenv tys + | TOp.TraitCall traitInfo, _, _ -> + let tysR = ConvTypes cenv traitInfo.SupportTypes let tyargsR = ConvTypes cenv tyargs - let argTysR = ConvTypes cenv argTys + let argTysR = ConvTypes cenv traitInfo.CompiledObjectAndArgumentTypes let argsR = ConvExprs cenv env args - E.TraitCall(tysR, nm, memFlags, argTysR, tyargsR, argsR) + E.TraitCall(tysR, traitInfo.MemberLogicalName, traitInfo.MemberFlags, argTysR, tyargsR, argsR) | TOp.RefAddrGet readonly, [ty], [e] -> let replExpr = mkRecdFieldGetAddrViaExprAddr(readonly, e, mkRefCellContentsRef g, [ty], m) diff --git a/src/Compiler/Symbols/SymbolHelpers.fs b/src/Compiler/Symbols/SymbolHelpers.fs index 8e69702800c..940f97a3e6f 100644 --- a/src/Compiler/Symbols/SymbolHelpers.fs +++ b/src/Compiler/Symbols/SymbolHelpers.fs @@ -2,6 +2,7 @@ namespace FSharp.Compiler.Symbols +open System open System.IO open Internal.Utilities.Library @@ -117,8 +118,7 @@ module internal SymbolHelpers = | Item.ImplicitOp (_, {contents = Some(TraitConstraintSln.FSMethSln(vref=vref))}) -> Some vref.Range | Item.ImplicitOp _ -> None | Item.UnqualifiedType tcrefs -> tcrefs |> List.tryPick (rangeOfEntityRef preferFlag >> Some) - | Item.DelegateCtor ty - | Item.FakeInterfaceCtor ty -> ty |> tryNiceEntityRefOfTyOption |> Option.map (rangeOfEntityRef preferFlag) + | Item.DelegateCtor ty -> ty |> tryNiceEntityRefOfTyOption |> Option.map (rangeOfEntityRef preferFlag) | Item.NewDef _ -> None // Provided type definitions do not have a useful F# CCU for the purposes of goto-definition. @@ -189,7 +189,6 @@ module internal SymbolHelpers = | Item.Types(_, tys) -> tys |> List.tryPick (tryNiceEntityRefOfTyOption >> Option.bind computeCcuOfTyconRef) - | Item.FakeInterfaceCtor(ty) | Item.DelegateCtor(ty) -> ty |> tryNiceEntityRefOfTyOption |> Option.bind computeCcuOfTyconRef @@ -282,7 +281,6 @@ module internal SymbolHelpers = | Item.ILField finfo -> mkXmlComment (GetXmlDocSigOfILFieldInfo infoReader m finfo) - | Item.FakeInterfaceCtor ty | Item.DelegateCtor ty | Item.Types(_, ty :: _) -> match ty with @@ -362,7 +360,6 @@ module internal SymbolHelpers = match item with | Item.DelegateCtor ty | Item.CtorGroup(_, [DefaultStructCtor(_, ty)]) - | Item.FakeInterfaceCtor ty | Item.Types(_, [ty]) -> Some ty | _ -> None @@ -397,7 +394,6 @@ module internal SymbolHelpers = | Item.ActivePatternResult _ | Item.AnonRecdField _ | Item.OtherName _ - | Item.FakeInterfaceCtor _ | Item.ImplicitOp _ | Item.NewDef _ | Item.UnionCaseField _ @@ -503,7 +499,6 @@ module internal SymbolHelpers = | Item.ActivePatternResult _ | Item.AnonRecdField _ | Item.OtherName _ - | Item.FakeInterfaceCtor _ | Item.ImplicitOp _ | Item.NewDef _ | Item.UnionCaseField _ @@ -571,7 +566,6 @@ module internal SymbolHelpers = | Item.MethodGroup(_, _, Some minfo) -> buildString (fun os -> NicePrint.outputTyconRef denv os minfo.DeclaringTyconRef; bprintf os ".%s" minfo.DisplayName) | Item.MethodGroup(_, minfo :: _, _) -> buildString (fun os -> NicePrint.outputTyconRef denv os minfo.DeclaringTyconRef; bprintf os ".%s" minfo.DisplayName) | Item.UnqualifiedType (tcref :: _) -> buildString (fun os -> NicePrint.outputTyconRef denv os tcref) - | Item.FakeInterfaceCtor ty | Item.DelegateCtor ty | Item.Types(_, ty :: _) -> match tryTcrefOfAppTy g ty with @@ -716,7 +710,6 @@ module internal SymbolHelpers = | Item.ActivePatternResult _ | Item.NewDef _ | Item.ILField _ - | Item.FakeInterfaceCtor _ | Item.DelegateCtor _ -> //| _ -> GetXmlCommentForItemAux None infoReader m item @@ -848,7 +841,6 @@ module internal SymbolHelpers = #endif | Item.Types(_, AppTy g (tcref, _) :: _) | Item.DelegateCtor(AppTy g (tcref, _)) - | Item.FakeInterfaceCtor(AppTy g (tcref, _)) | Item.UnqualifiedType (tcref :: _) | Item.ExnCase tcref -> // strip off any abbreviation @@ -859,7 +851,6 @@ module internal SymbolHelpers = // Pathological cases of the above | Item.Types _ | Item.DelegateCtor _ - | Item.FakeInterfaceCtor _ | Item.UnqualifiedType [] -> None @@ -876,7 +867,7 @@ module internal SymbolHelpers = // works similar to generation of xml-docs at tastops.fs, probably too similar // TODO: check if this code can be implemented using xml-doc generation functionality let prefix = path.AccessPath |> Seq.map fst |> String.concat "." - let fullName = if prefix = "" then modref.CompiledName else prefix + "." + modref.CompiledName + let fullName = if String.IsNullOrEmpty(prefix) then modref.CompiledName else prefix + "." + modref.CompiledName Some fullName ) #endif @@ -958,7 +949,6 @@ module internal SymbolHelpers = minfos |> List.map (fun minfo -> { Item = Item.MethodGroup(nm, [minfo], orig); TyparInstantiation = item.TyparInstantiation }) | Item.CtorGroup(nm, cinfos) -> cinfos |> List.map (fun minfo -> { Item = Item.CtorGroup(nm, [minfo]); TyparInstantiation = item.TyparInstantiation }) - | Item.FakeInterfaceCtor _ | Item.DelegateCtor _ -> [item] | Item.NewDef _ | Item.ILField _ -> [] diff --git a/src/Compiler/Symbols/Symbols.fs b/src/Compiler/Symbols/Symbols.fs index bc8ffaf1b1f..6527baf8f2d 100644 --- a/src/Compiler/Symbols/Symbols.fs +++ b/src/Compiler/Symbols/Symbols.fs @@ -331,7 +331,6 @@ type FSharpSymbol(cenv: SymbolEnv, item: unit -> Item, access: FSharpSymbol -> C // TODO: the following don't currently return any interesting subtype | Item.ImplicitOp _ | Item.ILField _ - | Item.FakeInterfaceCtor _ | Item.NewDef _ -> dflt() // These cases cover unreachable cases | Item.CustomOperation (_, _, None) @@ -1461,18 +1460,18 @@ type FSharpGenericParameterMemberConstraint(cenv, info: TraitConstraintInfo) = (fun () -> Item.Trait(info)), (fun _ _ _ad -> true)) - let (TTrait(tys, nm, flags, atys, retTy, _)) = info member _.MemberSources = - tys |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection + info.SupportTypes |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection - member _.MemberName = nm + member _.MemberName = info.MemberLogicalName - member _.MemberIsStatic = not flags.IsInstance + member _.MemberIsStatic = not info.MemberFlags.IsInstance - member _.MemberArgumentTypes = atys |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection + member _.MemberArgumentTypes = + info.CompiledObjectAndArgumentTypes |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection member _.MemberReturnType = - match retTy with + match info.CompiledReturnType with | None -> FSharpType(cenv, cenv.g.unit_ty) | Some ty -> FSharpType(cenv, ty) override x.ToString() = "" diff --git a/src/Compiler/SyntaxTree/LexFilter.fs b/src/Compiler/SyntaxTree/LexFilter.fs index 397eb0651b5..63e0ab3516a 100644 --- a/src/Compiler/SyntaxTree/LexFilter.fs +++ b/src/Compiler/SyntaxTree/LexFilter.fs @@ -4,6 +4,7 @@ /// Implements the offside rule and a couple of other lexical transformations. module internal FSharp.Compiler.LexFilter +open System open System.Collections.Generic open Internal.Utilities.Text.Lexing open FSharp.Compiler @@ -537,7 +538,7 @@ let (|TyparsCloseOp|_|) (txt: string) = | "$" -> Some DOLLAR | "%" -> Some (PERCENT_OP("%") ) | "%%" -> Some (PERCENT_OP("%%")) - | "" -> None + | s when String.IsNullOrEmpty(s) -> None | s -> match List.ofSeq afterAngles with | '=' :: _ diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs index bb2e7755767..cd4b41787e1 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fs +++ b/src/Compiler/SyntaxTree/ParseHelpers.fs @@ -1159,7 +1159,7 @@ let mkSynField let mType, mStart = idOpt - |> Option.map _.idRange + |> Option.map (fun x -> x.idRange) |> Option.orElseWith (fun _ -> vis |> Option.map (fun v -> v.Range)) |> Option.orElse isMutable |> Option.orElseWith (fun _ -> leadingKeyword |> Option.map (fun k -> k.Range)) diff --git a/src/Compiler/SyntaxTree/PrettyNaming.fs b/src/Compiler/SyntaxTree/PrettyNaming.fs index 1e67b7166b1..62f4ce8476c 100755 --- a/src/Compiler/SyntaxTree/PrettyNaming.fs +++ b/src/Compiler/SyntaxTree/PrettyNaming.fs @@ -1034,7 +1034,7 @@ let MangleProvidedTypeName (typeLogicalName, nonDefaultArgs) = let nonDefaultArgsText = nonDefaultArgs |> Array.map mangleStaticStringArg |> String.concat "," - if nonDefaultArgsText = "" then + if String.IsNullOrEmpty(nonDefaultArgsText) then typeLogicalName else typeLogicalName + "," + nonDefaultArgsText diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs index d47b2620b44..aae54549038 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fs +++ b/src/Compiler/SyntaxTree/SyntaxTree.fs @@ -1193,7 +1193,7 @@ type SynTypeDefnSimpleRepr = fields: SynField list * isConcrete: bool * isIncrClass: bool * - implicitCtorSynPats: SynSimplePats option * + implicitCtorSynPats: SynPat option * range: range | LibraryOnlyILAssembly of @@ -1442,7 +1442,7 @@ type SynMemberDefn = | ImplicitCtor of accessibility: SynAccess option * attributes: SynAttributes * - ctorArgs: SynSimplePats * + ctorArgs: SynPat * selfIdentifier: Ident option * xmlDoc: PreXmlDoc * range: range * diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi index 63ebdc6e448..0c278067a80 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi @@ -1351,7 +1351,7 @@ type SynTypeDefnSimpleRepr = fields: SynField list * isConcrete: bool * isIncrClass: bool * - implicitCtorSynPats: SynSimplePats option * + implicitCtorSynPats: SynPat option * range: range /// A type defined by using an IL assembly representation. Only used in FSharp.Core. @@ -1622,7 +1622,7 @@ type SynMemberDefn = | ImplicitCtor of accessibility: SynAccess option * attributes: SynAttributes * - ctorArgs: SynSimplePats * + ctorArgs: SynPat * selfIdentifier: Ident option * xmlDoc: PreXmlDoc * range: range * diff --git a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs index 4f259854614..d44395dbcc1 100644 --- a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs +++ b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs @@ -409,7 +409,10 @@ let opNameQMark = CompileOpName qmark let mkSynOperator (opm: range) (oper: string) = let trivia = - if oper.StartsWith("~") && ((opm.EndColumn - opm.StartColumn) = (oper.Length - 1)) then + if + oper.StartsWithOrdinal("~") + && ((opm.EndColumn - opm.StartColumn) = (oper.Length - 1)) + then // PREFIX_OP token where the ~ was actually absent IdentTrivia.OriginalNotation(string (oper.[1..])) else diff --git a/src/Compiler/SyntaxTree/XmlDoc.fs b/src/Compiler/SyntaxTree/XmlDoc.fs index 0bfb9c09f48..74135a6ba33 100644 --- a/src/Compiler/SyntaxTree/XmlDoc.fs +++ b/src/Compiler/SyntaxTree/XmlDoc.fs @@ -23,7 +23,7 @@ type XmlDoc(unprocessedLines: string[], range: range) = | lineA :: rest as lines -> let lineAT = lineA.TrimStart([| ' ' |]) - if lineAT = "" then + if String.IsNullOrEmpty(lineAT) then processLines rest elif lineAT.StartsWithOrdinal("<") then lines diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs index 152ab480dfd..cc67a69edab 100644 --- a/src/Compiler/TypedTree/TcGlobals.fs +++ b/src/Compiler/TypedTree/TcGlobals.fs @@ -1559,7 +1559,6 @@ type TcGlobals( member val attrib_CompilerFeatureRequiredAttribute = findSysAttrib "System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute" member val attrib_SetsRequiredMembersAttribute = findSysAttrib "System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute" member val attrib_RequiredMemberAttribute = findSysAttrib "System.Runtime.CompilerServices.RequiredMemberAttribute" - member val attrib_TailCallAttribute = mk_MFCore_attrib "TailCallAttribute" member g.improveType tcref tinst = improveTy tcref tinst @@ -1880,11 +1879,11 @@ type TcGlobals( member _.DebuggerBrowsableNeverAttribute = debuggerBrowsableNeverAttribute - member _.mkDebuggableAttributeV2(jitTracking, jitOptimizerDisabled, enableEnC) = + member _.mkDebuggableAttributeV2(jitTracking, jitOptimizerDisabled) = let debuggingMode = + 0x3 (* Default ||| IgnoreSymbolStoreSequencePoints *) ||| (if jitTracking then 1 else 0) ||| - (if jitOptimizerDisabled then 256 else 0) ||| - (if enableEnC then 4 else 0) + (if jitOptimizerDisabled then 256 else 0) let tref_DebuggableAttribute_DebuggingModes = mkILTyRefInTyRef (tref_DebuggableAttribute, tname_DebuggableAttribute_DebuggingModes) mkILCustomAttribute (tref_DebuggableAttribute, [mkILNonGenericValueTy tref_DebuggableAttribute_DebuggingModes], @@ -1897,6 +1896,10 @@ type TcGlobals( member _.DebuggerNonUserCodeAttribute = debuggerNonUserCodeAttribute + member _.HasTailCallAttrib (attribs: Attribs) = + attribs + |> List.exists (fun a -> a.TyconRef.CompiledRepresentationForNamedType.FullName = "Microsoft.FSharp.Core.TailCallAttribute") + member _.MakeInternalsVisibleToAttribute(simpleAssemName) = mkILCustomAttribute (tref_InternalsVisibleToAttribute, [ilg.typ_String], [ILAttribElem.String (Some simpleAssemName)], []) @@ -1906,7 +1909,7 @@ type TcGlobals( let memberName = let nm = t.MemberLogicalName let coreName = - if nm.StartsWith "op_" then nm[3..] + if nm.StartsWithOrdinal "op_" then nm[3..] elif nm = "get_Zero" then "GenericZero" elif nm = "get_One" then "GenericOne" else nm diff --git a/src/Compiler/TypedTree/TypedTree.fs b/src/Compiler/TypedTree/TypedTree.fs index e377213c329..e9028ca32cd 100644 --- a/src/Compiler/TypedTree/TypedTree.fs +++ b/src/Compiler/TypedTree/TypedTree.fs @@ -2461,29 +2461,41 @@ type TraitWitnessInfo = type TraitConstraintInfo = /// Indicates the signature of a member constraint. Contains a mutable solution cell - /// to store the inferred solution of the constraint. - | TTrait of tys: TTypes * memberName: string * memberFlags: SynMemberFlags * objAndArgTys: TTypes * returnTyOpt: TType option * solution: TraitConstraintSln option ref + /// to store the inferred solution of the constraint. And a mutable source cell to store + /// the name of the type or member that defined the constraint. + | TTrait of + tys: TTypes * + memberName: string * + memberFlags: SynMemberFlags * + objAndArgTys: TTypes * + returnTyOpt: TType option * + source: string option ref * + solution: TraitConstraintSln option ref /// Get the types that may provide solutions for the traits - member x.SupportTypes = (let (TTrait(tys, _, _, _, _, _)) = x in tys) + member x.SupportTypes = (let (TTrait(tys = tys)) = x in tys) /// Get the logical member name associated with the member constraint. - member x.MemberLogicalName = (let (TTrait(_, nm, _, _, _, _)) = x in nm) + member x.MemberLogicalName = (let (TTrait(memberName = nm)) = x in nm) /// Get the member flags associated with the member constraint. - member x.MemberFlags = (let (TTrait(_, _, flags, _, _, _)) = x in flags) - - member x.CompiledObjectAndArgumentTypes = (let (TTrait(_, _, _, objAndArgTys, _, _)) = x in objAndArgTys) - - member x.WithMemberKind(kind) = (let (TTrait(a, b, c, d, e, f)) = x in TTrait(a, b, { c with MemberKind=kind }, d, e, f)) + member x.MemberFlags = (let (TTrait(memberFlags = flags)) = x in flags) + member x.CompiledObjectAndArgumentTypes = (let (TTrait(objAndArgTys = objAndArgTys)) = x in objAndArgTys) + /// Get the optional return type recorded in the member constraint. - member x.CompiledReturnType = (let (TTrait(_, _, _, _, retTy, _)) = x in retTy) - + member x.CompiledReturnType = (let (TTrait(returnTyOpt = retTy)) = x in retTy) + /// Get or set the solution of the member constraint during inference member x.Solution - with get() = (let (TTrait(_, _, _, _, _, sln)) = x in sln.Value) - and set v = (let (TTrait(_, _, _, _, _, sln)) = x in sln.Value <- v) + with get() = (let (TTrait(solution = sln)) = x in sln.Value) + and set v = (let (TTrait(solution = sln)) = x in sln.Value <- v) + + member x.WithMemberKind(kind) = (let (TTrait(a, b, c, d, e, f, g)) = x in TTrait(a, b, { c with MemberKind=kind }, d, e, f, g)) + + member x.WithSupportTypes(tys) = (let (TTrait(_, b, c, d, e, f, g)) = x in TTrait(tys, b, c, d, e, f, g)) + + member x.WithMemberName(name) = (let (TTrait(a, _, c, d, e, f, g)) = x in TTrait(a, name, c, d, e, f, g)) [] member x.DebugText = x.ToString() diff --git a/src/Compiler/TypedTree/TypedTree.fsi b/src/Compiler/TypedTree/TypedTree.fsi index a2f167130e6..f40713b2f3e 100644 --- a/src/Compiler/TypedTree/TypedTree.fsi +++ b/src/Compiler/TypedTree/TypedTree.fsi @@ -1681,13 +1681,15 @@ type TraitWitnessInfo = type TraitConstraintInfo = /// Indicates the signature of a member constraint. Contains a mutable solution cell - /// to store the inferred solution of the constraint. + /// to store the inferred solution of the constraint. And a mutable source cell to store + /// the name of the type or member that defined the constraint. | TTrait of tys: TTypes * memberName: string * memberFlags: Syntax.SynMemberFlags * objAndArgTys: TTypes * returnTyOpt: TType option * + source: string option ref * solution: TraitConstraintSln option ref override ToString: unit -> string @@ -1722,6 +1724,10 @@ type TraitConstraintInfo = /// the extension property MemberDisplayNameCore member WithMemberKind: SynMemberKind -> TraitConstraintInfo + member WithSupportTypes: TTypes -> TraitConstraintInfo + + member WithMemberName: string -> TraitConstraintInfo + /// Represents the solution of a member constraint during inference. [] type TraitConstraintSln = diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs index 1af0df92d43..cf75136829d 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.fs @@ -3,6 +3,7 @@ /// Defines derived expression manipulation and construction functions. module internal FSharp.Compiler.TypedTreeOps +open System open System.CodeDom.Compiler open System.Collections.Generic open System.Collections.Immutable @@ -263,7 +264,7 @@ and remapTyparConstraintsAux tyenv cs = | TyparConstraint.IsReferenceType _ | TyparConstraint.RequiresDefaultConstructor _ -> Some x) -and remapTraitInfo tyenv (TTrait(tys, nm, flags, argTys, retTy, slnCell)) = +and remapTraitInfo tyenv (TTrait(tys, nm, flags, argTys, retTy, source, slnCell)) = let slnCell = match slnCell.Value with | None -> None @@ -299,7 +300,7 @@ and remapTraitInfo tyenv (TTrait(tys, nm, flags, argTys, retTy, slnCell)) = // in the same way as types let newSlnCell = ref slnCell - TTrait(tysR, nm, flags, argTysR, retTyR, newSlnCell) + TTrait(tysR, nm, flags, argTysR, retTyR, source, newSlnCell) and bindTypars tps tyargs tpinst = match tps with @@ -968,8 +969,8 @@ type TypeEquivEnv with TypeEquivEnv.Empty.BindEquivTypars tps1 tps2 let rec traitsAEquivAux erasureFlag g aenv traitInfo1 traitInfo2 = - let (TTrait(tys1, nm, mf1, argTys, retTy, _)) = traitInfo1 - let (TTrait(tys2, nm2, mf2, argTys2, retTy2, _)) = traitInfo2 + let (TTrait(tys1, nm, mf1, argTys, retTy, _, _)) = traitInfo1 + let (TTrait(tys2, nm2, mf2, argTys2, retTy2, _, _)) = traitInfo2 mf1.IsInstance = mf2.IsInstance && nm = nm2 && ListSet.equals (typeAEquivAux erasureFlag g aenv) tys1 tys2 && @@ -2315,7 +2316,7 @@ and accFreeInTyparConstraint opts tpc acc = | TyparConstraint.IsUnmanaged _ | TyparConstraint.RequiresDefaultConstructor _ -> acc -and accFreeInTrait opts (TTrait(tys, _, _, argTys, retTy, sln)) acc = +and accFreeInTrait opts (TTrait(tys, _, _, argTys, retTy, _, sln)) acc = Option.foldBack (accFreeInTraitSln opts) sln.Value (accFreeInTypes opts tys (accFreeInTypes opts argTys @@ -2451,7 +2452,7 @@ and accFreeInTyparConstraintLeftToRight g cxFlag thruFlag acc tpc = | TyparConstraint.IsReferenceType _ | TyparConstraint.RequiresDefaultConstructor _ -> acc -and accFreeInTraitLeftToRight g cxFlag thruFlag acc (TTrait(tys, _, _, argTys, retTy, _)) = +and accFreeInTraitLeftToRight g cxFlag thruFlag acc (TTrait(tys, _, _, argTys, retTy, _, _)) = let acc = accFreeInTypesLeftToRight g cxFlag thruFlag acc tys let acc = accFreeInTypesLeftToRight g cxFlag thruFlag acc argTys let acc = Option.fold (accFreeInTypeLeftToRight g cxFlag thruFlag) acc retTy @@ -2658,7 +2659,7 @@ type TraitConstraintInfo with /// Get the key associated with the member constraint. member traitInfo.GetWitnessInfo() = - let (TTrait(tys, nm, memFlags, objAndArgTys, rty, _)) = traitInfo + let (TTrait(tys, nm, memFlags, objAndArgTys, rty, _, _)) = traitInfo TraitWitnessInfo(tys, nm, memFlags, objAndArgTys, rty) /// Get information about the trait constraints for a set of typars. @@ -3209,7 +3210,7 @@ type DisplayEnv = ControlPath (splitNamespace ExtraTopLevelOperatorsName) ] -let (+.+) s1 s2 = if s1 = "" then s2 else s1+"."+s2 +let (+.+) s1 s2 = if String.IsNullOrEmpty(s1) then s2 else s1+"."+s2 let layoutOfPath p = sepListL SepL.dot (List.map (tagNamespace >> wordL) p) @@ -4078,7 +4079,7 @@ module DebugPrint = and auxTraitL env (ttrait: TraitConstraintInfo) = #if DEBUG - let (TTrait(tys, nm, memFlags, argTys, retTy, _)) = ttrait + let (TTrait(tys, nm, memFlags, argTys, retTy, _, _)) = ttrait match global_g with | None -> wordL (tagText "") | Some g -> @@ -5413,7 +5414,7 @@ and accFreeInOp opts op acc = | TOp.Reraise -> accUsesRethrow true acc - | TOp.TraitCall (TTrait(tys, _, _, argTys, retTy, sln)) -> + | TOp.TraitCall (TTrait(tys, _, _, argTys, retTy, _, sln)) -> Option.foldBack (accFreeVarsInTraitSln opts) sln.Value (accFreeVarsInTys opts tys (accFreeVarsInTys opts argTys @@ -8831,7 +8832,7 @@ let buildAccessPath (cp: CompilationPath option) = System.String.Join(".", ap) | None -> "Extension Type" -let prependPath path name = if path = "" then name else path + "." + name +let prependPath path name = if String.IsNullOrEmpty(path) then name else path + "." + name let XmlDocSigOfVal g full path (v: Val) = let parentTypars, methTypars, cxs, argInfos, retTy, prefix, path, name = @@ -10516,7 +10517,7 @@ let (|SequentialResumableCode|_|) (g: TcGlobals) expr = Some (e1, e2, m, (fun e1 e2 -> Expr.Sequential(e1, e2, NormalSeq, m))) // let __stack_step = e1 in e2 - | Expr.Let(bind, e2, m, _) when bind.Var.CompiledName(g.CompilerGlobalState).StartsWith(stackVarPrefix) -> + | Expr.Let(bind, e2, m, _) when bind.Var.CompiledName(g.CompilerGlobalState).StartsWithOrdinal(stackVarPrefix) -> Some (bind.Expr, e2, m, (fun e1 e2 -> mkLet bind.DebugPoint m bind.Var e1 e2)) | _ -> None @@ -10691,23 +10692,42 @@ let (|EmptyModuleOrNamespaces|_|) (moduleOrNamespaceContents: ModuleOrNamespaceC None | _ -> None -let tryAddExtensionAttributeIfNotAlreadyPresent +let tryFindExtensionAttribute (g: TcGlobals) (attribs: Attrib list): Attrib option = + attribs + |> List.tryFind (IsMatchingFSharpAttribute g g.attrib_ExtensionAttribute) + +let tryAddExtensionAttributeIfNotAlreadyPresentForModule + (g: TcGlobals) + (tryFindExtensionAttributeIn: (Attrib list -> Attrib option) -> Attrib option) + (moduleEntity: Entity) + : Entity + = + if Option.isSome (tryFindExtensionAttribute g moduleEntity.Attribs) then + moduleEntity + else + match tryFindExtensionAttributeIn (tryFindExtensionAttribute g) with + | None -> moduleEntity + | Some extensionAttrib -> + { moduleEntity with entity_attribs = extensionAttrib :: moduleEntity.Attribs } + +let tryAddExtensionAttributeIfNotAlreadyPresentForType + (g: TcGlobals) (tryFindExtensionAttributeIn: (Attrib list -> Attrib option) -> Attrib option) - (entity: Entity) + (moduleOrNamespaceTypeAccumulator: ModuleOrNamespaceType ref) + (typeEntity: Entity) : Entity = - let tryFindExtensionAttribute (attribs: Attrib list): Attrib option = - List.tryFind - (fun (a: Attrib) -> - a.TyconRef.CompiledRepresentationForNamedType.BasicQualifiedName = "System.Runtime.CompilerServices.ExtensionAttribute") - attribs - - if Option.isSome (tryFindExtensionAttribute entity.Attribs) then - entity + if Option.isSome (tryFindExtensionAttribute g typeEntity.Attribs) then + typeEntity else - match tryFindExtensionAttributeIn tryFindExtensionAttribute with - | None -> entity - | Some extensionAttrib -> { entity with entity_attribs = extensionAttrib :: entity.Attribs } + match tryFindExtensionAttributeIn (tryFindExtensionAttribute g) with + | None -> typeEntity + | Some extensionAttrib -> + moduleOrNamespaceTypeAccumulator.Value.AllEntitiesByLogicalMangledName.TryFind(typeEntity.LogicalName) + |> Option.iter (fun e -> + e.entity_attribs <- extensionAttrib :: e.Attribs + ) + typeEntity type TypedTreeNode = { diff --git a/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi index 7ad98c887e5..77b6347d983 100755 --- a/src/Compiler/TypedTree/TypedTreeOps.fsi +++ b/src/Compiler/TypedTree/TypedTreeOps.fsi @@ -2732,9 +2732,22 @@ type TraitConstraintInfo with val (|EmptyModuleOrNamespaces|_|): moduleOrNamespaceContents: ModuleOrNamespaceContents -> (ModuleOrNamespace list) option -/// Add an System.Runtime.CompilerServices.ExtensionAttribute to the Entity if found via predicate and not already present. -val tryAddExtensionAttributeIfNotAlreadyPresent: - tryFindExtensionAttributeIn: ((Attrib list -> Attrib option) -> Attrib option) -> entity: Entity -> Entity +val tryFindExtensionAttribute: g: TcGlobals -> attribs: Attrib list -> Attrib option + +/// Add an System.Runtime.CompilerServices.ExtensionAttribute to the module Entity if found via predicate and not already present. +val tryAddExtensionAttributeIfNotAlreadyPresentForModule: + g: TcGlobals -> + tryFindExtensionAttributeIn: ((Attrib list -> Attrib option) -> Attrib option) -> + moduleEntity: Entity -> + Entity + +/// Add an System.Runtime.CompilerServices.ExtensionAttribute to the type Entity if found via predicate and not already present. +val tryAddExtensionAttributeIfNotAlreadyPresentForType: + g: TcGlobals -> + tryFindExtensionAttributeIn: ((Attrib list -> Attrib option) -> Attrib option) -> + moduleOrNamespaceTypeAccumulator: ModuleOrNamespaceType ref -> + typeEntity: Entity -> + Entity /// Serialize an entity to a very basic json structure. val serializeEntity: path: string -> entity: Entity -> unit diff --git a/src/Compiler/TypedTree/TypedTreePickle.fs b/src/Compiler/TypedTree/TypedTreePickle.fs index 84ed2bf70d2..e855587e739 100644 --- a/src/Compiler/TypedTree/TypedTreePickle.fs +++ b/src/Compiler/TypedTree/TypedTreePickle.fs @@ -1516,7 +1516,7 @@ let p_trait_sln sln st = p_byte 7 st; p_tup4 p_ty (p_vref "trait") p_tys p_ty (a, b, c, d) st -let p_trait (TTrait(a, b, c, d, e, f)) st = +let p_trait (TTrait(a, b, c, d, e, _, f)) st = p_tup6 p_tys p_string p_MemberFlags p_tys (p_option p_ty) (p_option p_trait_sln) (a, b, c, d, e, f.Value) st let u_anonInfo_data st = @@ -1556,7 +1556,7 @@ let u_trait_sln st = let u_trait st = let a, b, c, d, e, f = u_tup6 u_tys u_string u_MemberFlags u_tys (u_option u_ty) (u_option u_trait_sln) st - TTrait (a, b, c, d, e, ref f) + TTrait (a, b, c, d, e, ref None, ref f) let p_rational q st = p_int32 (GetNumerator q) st; p_int32 (GetDenominator q) st diff --git a/src/Compiler/Utilities/Activity.fs b/src/Compiler/Utilities/Activity.fs index 22405544e2f..ed2ac738ed2 100644 --- a/src/Compiler/Utilities/Activity.fs +++ b/src/Compiler/Utilities/Activity.fs @@ -33,6 +33,7 @@ module internal Activity = let gc2 = "gc2" let outputDllFile = "outputDllFile" let buildPhase = "buildPhase" + let version = "version" let AllKnownTags = [| diff --git a/src/Compiler/Utilities/Activity.fsi b/src/Compiler/Utilities/Activity.fsi index 94784c97f00..afce0f3b554 100644 --- a/src/Compiler/Utilities/Activity.fsi +++ b/src/Compiler/Utilities/Activity.fsi @@ -1,5 +1,4 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - namespace FSharp.Compiler.Diagnostics open System @@ -29,6 +28,7 @@ module internal Activity = val length: string val cache: string val buildPhase: string + val version: string module Events = val cacheHit: string diff --git a/src/Compiler/Utilities/Cancellable.fs b/src/Compiler/Utilities/Cancellable.fs index c702e3b7a0b..59e7def4c10 100644 --- a/src/Compiler/Utilities/Cancellable.fs +++ b/src/Compiler/Utilities/Cancellable.fs @@ -2,32 +2,47 @@ namespace FSharp.Compiler open System open System.Threading +open Internal.Utilities.Library [] type Cancellable = [] - static val mutable private token: CancellationToken - - static member UsingToken(ct) = - let oldCt = Cancellable.token - - Cancellable.token <- ct + static val mutable private tokens: CancellationToken list + static let disposable = { new IDisposable with - member this.Dispose() = Cancellable.token <- oldCt + member this.Dispose() = + Cancellable.Tokens <- Cancellable.Tokens |> List.tail } - static member Token - with get () = Cancellable.token - and internal set v = Cancellable.token <- v + static member Tokens + with private get () = + match box Cancellable.tokens with + | Null -> [] + | _ -> Cancellable.tokens + and private set v = Cancellable.tokens <- v + + static member UsingToken(ct) = + Cancellable.Tokens <- ct :: Cancellable.Tokens + disposable + + static member Token = + match Cancellable.Tokens with + | [] -> CancellationToken.None + | token :: _ -> token + /// There may be multiple tokens if `UsingToken` is called multiple times, producing scoped structure. + /// We're interested in the current, i.e. the most recent, one. static member CheckAndThrow() = - Cancellable.token.ThrowIfCancellationRequested() + match Cancellable.Tokens with + | [] -> () + | token :: _ -> token.ThrowIfCancellationRequested() namespace Internal.Utilities.Library open System open System.Threading +open FSharp.Compiler #if !FSHARPCORE_USE_PACKAGE open FSharp.Core.CompilerServices.StateMachineHelpers @@ -48,6 +63,7 @@ module Cancellable = ValueOrCancelled.Cancelled(OperationCanceledException ct) else try + use _ = Cancellable.UsingToken(ct) oper ct with :? OperationCanceledException as e -> ValueOrCancelled.Cancelled(OperationCanceledException e.CancellationToken) diff --git a/src/Compiler/Utilities/Cancellable.fsi b/src/Compiler/Utilities/Cancellable.fsi index 6e36d7ecb6d..23515432bdd 100644 --- a/src/Compiler/Utilities/Cancellable.fsi +++ b/src/Compiler/Utilities/Cancellable.fsi @@ -7,7 +7,6 @@ open System.Threading type Cancellable = static member internal UsingToken: CancellationToken -> IDisposable static member Token: CancellationToken - static member internal Token: CancellationToken with set static member CheckAndThrow: unit -> unit namespace Internal.Utilities.Library diff --git a/src/Compiler/Utilities/FileSystem.fs b/src/Compiler/Utilities/FileSystem.fs index 5b555915e6c..8023eacb942 100644 --- a/src/Compiler/Utilities/FileSystem.fs +++ b/src/Compiler/Utilities/FileSystem.fs @@ -616,16 +616,16 @@ type DefaultFileSystem() as this = default _.IsInvalidPathShim(path: string) = let isInvalidPath (p: string MaybeNull) = - match p with - | Null - | "" -> true - | NonNull p -> p.IndexOfAny(Path.GetInvalidPathChars()) <> -1 + if String.IsNullOrEmpty(p) then + true + else + p.IndexOfAny(Path.GetInvalidPathChars()) <> -1 let isInvalidFilename (p: string MaybeNull) = - match p with - | Null - | "" -> true - | NonNull p -> p.IndexOfAny(Path.GetInvalidFileNameChars()) <> -1 + if String.IsNullOrEmpty(p) then + true + else + p.IndexOfAny(Path.GetInvalidFileNameChars()) <> -1 let isInvalidDirectory (d: string MaybeNull) = match d with @@ -645,7 +645,7 @@ type DefaultFileSystem() as this = default _.GetDirectoryNameShim(path: string) = FileSystemUtils.checkPathForIllegalChars path - if path = "" then + if String.IsNullOrEmpty(path) then "." else match Path.GetDirectoryName(path) with @@ -654,7 +654,7 @@ type DefaultFileSystem() as this = path else "." - | res -> if res = "" then "." else res + | res -> if String.IsNullOrEmpty(res) then "." else res abstract GetLastWriteTimeShim: fileName: string -> DateTime default _.GetLastWriteTimeShim(fileName: string) = File.GetLastWriteTimeUtc fileName diff --git a/src/Compiler/Utilities/LruCache.fs b/src/Compiler/Utilities/LruCache.fs new file mode 100644 index 00000000000..c75ed1d88cf --- /dev/null +++ b/src/Compiler/Utilities/LruCache.fs @@ -0,0 +1,273 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Internal.Utilities.Collections + +open System +open System.Collections.Generic +open System.Diagnostics + +open Internal.Utilities.Library.Extras + +[] +type internal CacheEvent = + | Evicted + | Collected + | Weakened + | Strengthened + | Cleared + +[] +type internal ValueLink<'T when 'T: not struct> = + | Strong of 'T + | Weak of WeakReference<'T> + +[] +type internal LruCache<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'TVersion: equality and 'TValue: not struct> + (keepStrongly, ?keepWeakly, ?requiredToKeep, ?event) = + + let keepWeakly = defaultArg keepWeakly 100 + let requiredToKeep = defaultArg requiredToKeep (fun _ -> false) + let event = defaultArg event (fun _ _ -> ()) + + let dictionary = Dictionary<'TKey, Dictionary<'TVersion, _>>() + + // Lists to keep track of when items were last accessed. First item is most recently accessed. + let strongList = LinkedList<'TKey * 'TVersion * string * ValueLink<'TValue>>() + let weakList = LinkedList<'TKey * 'TVersion * string * ValueLink<'TValue>>() + + let rec removeCollected (node: LinkedListNode<_>) = + if node <> null then + let key, version, label, value = node.Value + + match value with + | Weak w -> + let next = node.Next + + match w.TryGetTarget() with + | false, _ -> + weakList.Remove node + dictionary[key].Remove version |> ignore + + if dictionary[key].Count = 0 then + dictionary.Remove key |> ignore + + event CacheEvent.Collected (label, key, version) + | _ -> () + + removeCollected next + | _ -> failwith "Illegal state, strong reference in weak list" + + let cutWeakListIfTooLong () = + if weakList.Count > keepWeakly then + removeCollected weakList.First + + let mutable node = weakList.Last + + while weakList.Count > keepWeakly && node <> null do + let previous = node.Previous + let key, version, label, _ = node.Value + weakList.Remove node + dictionary[key].Remove version |> ignore + + if dictionary[key].Count = 0 then + dictionary.Remove key |> ignore + + event CacheEvent.Evicted (label, key, version) + node <- previous + + let cutStrongListIfTooLong () = + let mutable node = strongList.Last + + let mutable anythingWeakened = false + + while strongList.Count > keepStrongly && node <> null do + let previous = node.Previous + + match node.Value with + | _, _, _, Strong v when requiredToKeep v -> () + | key, version, label, Strong v -> + strongList.Remove node + node.Value <- key, version, label, Weak(WeakReference<_> v) + weakList.AddFirst node + event CacheEvent.Weakened (label, key, version) + anythingWeakened <- true + | _key, _version, _label, _ -> failwith "Invalid state, weak reference in strong list" + + node <- previous + + if anythingWeakened then + cutWeakListIfTooLong () + + let pushNodeToTop (node: LinkedListNode<_>) = + match node.Value with + | _, _, _, Strong _ -> + strongList.AddFirst node + cutStrongListIfTooLong () + | _, _, _, Weak _ -> failwith "Invalid operation, pushing weak reference to strong list" + + let pushValueToTop key version label value = + strongList.AddFirst(value = (key, version, label, Strong value)) + + member _.DebuggerDisplay = $"Cache(S:{strongList.Count} W:{weakList.Count})" + + member _.Set(key, version, label, value) = + match dictionary.TryGetValue key with + | true, versionDict -> + + if versionDict.ContainsKey version then + // TODO this is normal for unversioned cache; + // failwith "Suspicious - overwriting existing version" + + let node: LinkedListNode<_> = versionDict[version] + + match node.Value with + | _, _, _, Strong _ -> strongList.Remove node + | _, _, _, Weak _ -> + weakList.Remove node + event CacheEvent.Strengthened (label, key, version) + + node.Value <- key, version, label, Strong value + pushNodeToTop node + + else + let node = pushValueToTop key version label value + versionDict[version] <- node + // weaken all other versions (unless they're required to be kept) + let versionsToWeaken = versionDict.Keys |> Seq.filter ((<>) version) |> Seq.toList + + let mutable anythingWeakened = false + + for otherVersion in versionsToWeaken do + let node = versionDict[otherVersion] + + match node.Value with + | _, _, _, Strong value when not (requiredToKeep value) -> + strongList.Remove node + node.Value <- key, otherVersion, label, Weak(WeakReference<_> value) + weakList.AddFirst node + event CacheEvent.Weakened (label, key, otherVersion) + anythingWeakened <- true + | _ -> () + + if anythingWeakened then + cutWeakListIfTooLong () + else + cutStrongListIfTooLong () + + | false, _ -> + let node = pushValueToTop key version label value + cutStrongListIfTooLong () + dictionary[key] <- Dictionary() + dictionary[key][version] <- node + + member this.Set(key, version, value) = + this.Set(key, version, "[no label]", value) + + member _.TryGet(key, version) = + + match dictionary.TryGetValue key with + | false, _ -> None + | true, versionDict -> + match versionDict.TryGetValue version with + | false, _ -> None + | true, node -> + match node.Value with + | _, _, _, Strong v -> + strongList.Remove node + pushNodeToTop node + Some v + + | _, _, label, Weak w -> + match w.TryGetTarget() with + | true, value -> + weakList.Remove node + let node = pushValueToTop key version label value + event CacheEvent.Strengthened (label, key, version) + cutStrongListIfTooLong () + versionDict[version] <- node + Some value + | _ -> + weakList.Remove node + versionDict.Remove version |> ignore + + if versionDict.Count = 0 then + dictionary.Remove key |> ignore + + event CacheEvent.Collected (label, key, version) + None + + /// Returns an option of a value for given key and version, and also a list of all other versions for given key + member this.GetAll(key, version) = + this.TryGet(key, version), + + match dictionary.TryGetValue key with + | false, _ -> [] + | true, versionDict -> + versionDict.Values + |> Seq.map (fun node -> node.Value) + |> Seq.filter (p24 >> ((<>) version)) + |> Seq.choose (function + | _, ver, _, Strong v -> Some(ver, v) + | _, ver, _, Weak r -> + match r.TryGetTarget() with + | true, x -> Some(ver, x) + | _ -> None) + |> Seq.toList + + member _.Remove(key, version) = + match dictionary.TryGetValue key with + | false, _ -> () + | true, versionDict -> + match versionDict.TryGetValue version with + | true, node -> + versionDict.Remove version |> ignore + + if versionDict.Count = 0 then + dictionary.Remove key |> ignore + + match node.Value with + | _, _, _, Strong _ -> strongList.Remove node + | _, _, _, Weak _ -> weakList.Remove node + | _ -> () + + member this.Set(key, value) = + this.Set(key, Unchecked.defaultof<_>, value) + + member this.TryGet(key) = + this.TryGet(key, Unchecked.defaultof<_>) + + member this.Remove(key) = + this.Remove(key, Unchecked.defaultof<_>) + + member _.Clear() = + dictionary.Clear() + strongList.Clear() + weakList.Clear() + + member _.Clear(predicate) = + let keysToRemove = dictionary.Keys |> Seq.filter predicate |> Seq.toList + + for key in keysToRemove do + match dictionary.TryGetValue key with + | true, versionDict -> + versionDict.Values + |> Seq.iter (fun node -> + match node.Value with + | _, _, _, Strong _ -> strongList.Remove node + | _, _, _, Weak _ -> weakList.Remove node + + match node.Value with + | key, version, label, _ -> event CacheEvent.Cleared (label, key, version)) + + dictionary.Remove key |> ignore + | _ -> () + + member _.GetValues() = + strongList + |> Seq.append weakList + |> Seq.choose (function + | _k, version, label, Strong value -> Some(label, version, value) + | _k, version, label, Weak w -> + match w.TryGetTarget() with + | true, value -> Some(label, version, value) + | _ -> None) diff --git a/src/Compiler/Utilities/LruCache.fsi b/src/Compiler/Utilities/LruCache.fsi new file mode 100644 index 00000000000..d9aefd2a240 --- /dev/null +++ b/src/Compiler/Utilities/LruCache.fsi @@ -0,0 +1,52 @@ +namespace Internal.Utilities.Collections + +[] +type internal CacheEvent = + | Evicted + | Collected + | Weakened + | Strengthened + | Cleared + +/// A cache where least recently used items are removed when the cache is full. +/// +/// It's also versioned, meaning each key can have multiple versions and only the latest one is kept strongly. +/// Older versions are kept weakly and can be collected by GC. +type internal LruCache<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'TVersion: equality and 'TValue: not struct> = + + /// Maximum number of strongly held results to keep in the cache + /// Maximum number of weakly held results to keep in the cache + /// A predicate that determines if a value should be kept strongly (no matter what) + /// An event that is called when an item is evicted, collected, weakened or strengthened + new: + keepStrongly: int * + ?keepWeakly: int * + ?requiredToKeep: ('TValue -> bool) * + ?event: (CacheEvent -> string * 'TKey * 'TVersion -> unit) -> + LruCache<'TKey, 'TVersion, 'TValue> + + member Clear: unit -> unit + + /// Clear any keys that match the given predicate + member Clear: predicate: ('TKey -> bool) -> unit + + /// Returns an option of a value for given key and version, and also a list of all other versions for given key + member GetAll: key: 'TKey * version: 'TVersion -> 'TValue option * ('TVersion * 'TValue) list + + member GetValues: unit -> (string * 'TVersion * 'TValue) seq + + member Remove: key: 'TKey -> unit + + member Remove: key: 'TKey * version: 'TVersion -> unit + + member Set: key: 'TKey * value: 'TValue -> unit + + member Set: key: 'TKey * version: 'TVersion * value: 'TValue -> unit + + member Set: key: 'TKey * version: 'TVersion * label: string * value: 'TValue -> unit + + member TryGet: key: 'TKey -> 'TValue option + + member TryGet: key: 'TKey * version: 'TVersion -> 'TValue option + + member DebuggerDisplay: string diff --git a/src/Compiler/Utilities/PathMap.fs b/src/Compiler/Utilities/PathMap.fs index f11edef6a82..50319ea7079 100644 --- a/src/Compiler/Utilities/PathMap.fs +++ b/src/Compiler/Utilities/PathMap.fs @@ -6,6 +6,7 @@ namespace Internal.Utilities open System open System.IO +open Internal.Utilities.Library open FSharp.Compiler.IO type PathMap = PathMap of Map @@ -22,7 +23,7 @@ module internal PathMap = let normalSrc = FileSystem.GetFullPathShim src let oldPrefix = - if normalSrc.EndsWith dirSepStr then + if normalSrc.EndsWithOrdinal dirSepStr then normalSrc else normalSrc + dirSepStr @@ -41,7 +42,7 @@ module internal PathMap = // oldPrefix always ends with a path separator, so there's no need // to check if it was a partial match // e.g. for the map /goo=/bar and file name /goooo - if filePath.StartsWith(oldPrefix, StringComparison.Ordinal) then + if filePath.StartsWithOrdinal oldPrefix then let replacement = replacementPrefix + filePath.Substring(oldPrefix.Length - 1) // Normalize the path separators if used uniformly in the replacement @@ -60,7 +61,7 @@ module internal PathMap = |> Option.defaultValue filePath let applyDir pathMap (dirName: string) : string = - if dirName.EndsWith dirSepStr then + if dirName.EndsWithOrdinal dirSepStr then apply pathMap dirName else let mapped = apply pathMap (dirName + dirSepStr) diff --git a/src/Compiler/Utilities/illib.fs b/src/Compiler/Utilities/illib.fs index 6bf85595108..c4ecd88533e 100644 --- a/src/Compiler/Utilities/illib.fs +++ b/src/Compiler/Utilities/illib.fs @@ -129,6 +129,15 @@ module internal PervasiveAutoOpens = member inline x.EndsWithOrdinalIgnoreCase value = x.EndsWith(value, StringComparison.OrdinalIgnoreCase) + member inline x.IndexOfOrdinal value = + x.IndexOf(value, StringComparison.Ordinal) + + member inline x.IndexOfOrdinal(value, startIndex) = + x.IndexOf(value, startIndex, StringComparison.Ordinal) + + member inline x.IndexOfOrdinal(value, startIndex, count) = + x.IndexOf(value, startIndex, count, StringComparison.Ordinal) + /// Get an initialization hole let getHole (r: _ ref) = match r.Value with @@ -806,7 +815,7 @@ module String = String digits |> function - | "" -> str, None + | x when String.IsNullOrEmpty(x) -> str, None | index -> str.Substring(0, str.Length - index.Length), Some(int index) /// Splits a string into substrings based on the strings in the array separators diff --git a/src/Compiler/Utilities/illib.fsi b/src/Compiler/Utilities/illib.fsi index 266f884fa01..2df0d9c0959 100644 --- a/src/Compiler/Utilities/illib.fsi +++ b/src/Compiler/Utilities/illib.fsi @@ -85,6 +85,12 @@ module internal PervasiveAutoOpens = member inline EndsWithOrdinalIgnoreCase: value: string -> bool + member inline IndexOfOrdinal: value: string -> int + + member inline IndexOfOrdinal: value: string * startIndex: int -> int + + member inline IndexOfOrdinal: value: string * startIndex: int * count: int -> int + type Async with /// Runs the computation synchronously, always starting on the current thread. diff --git a/src/Compiler/Utilities/sformat.fs b/src/Compiler/Utilities/sformat.fs index 834e0c56ed3..611c31235d9 100644 --- a/src/Compiler/Utilities/sformat.fs +++ b/src/Compiler/Utilities/sformat.fs @@ -286,13 +286,13 @@ module Layout = let isEmptyL layout = match layout with - | Leaf(true, s, true) -> s.Text = "" + | Leaf(true, s, true) -> String.IsNullOrEmpty(s.Text) | _ -> false #if COMPILER let rec endsWithL (text: string) layout = match layout with - | Leaf(_, s, _) -> s.Text.EndsWith(text) + | Leaf(_, s, _) -> s.Text.EndsWith(text, StringComparison.Ordinal) | Node(_, r, _) -> endsWithL text r | Attr(_, _, l) -> endsWithL text l | ObjLeaf _ -> false @@ -519,7 +519,7 @@ module ReflectUtils = FSharpValue.GetTupleFields obj |> Array.mapi (fun i v -> (v, tyArgs[i])) let tupleType = - if reprty.Name.StartsWith "ValueTuple" then + if reprty.Name.StartsWith("ValueTuple", StringComparison.Ordinal) then TupleType.Value else TupleType.Reference @@ -1129,7 +1129,7 @@ module Display = :: layouts match postText with - | "" -> + | _ when String.IsNullOrEmpty(postText) -> //We are done, build a space-delimited layout from the collection of layouts we've accumulated Some(spaceListL (List.rev newLayouts)) diff --git a/src/Compiler/Utilities/sr.fs b/src/Compiler/Utilities/sr.fs index b081dfb6083..840a9f4197c 100644 --- a/src/Compiler/Utilities/sr.fs +++ b/src/Compiler/Utilities/sr.fs @@ -2,6 +2,7 @@ namespace FSharp.Compiler +open System open Microsoft.FSharp.Core open Microsoft.FSharp.Collections open Microsoft.FSharp.Reflection @@ -132,7 +133,7 @@ module internal DiagnosticMessage = // strip any escaped % characters - yes, this will fail if given %%%... let s = s.Replace("%%", "") - if s = "" then + if String.IsNullOrEmpty(s) then 0 else let len = s.Length - 1 diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 03e8c099e25..5737eba22f3 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -1614,7 +1614,7 @@ tyconDefn: SynTypeDefn($1, SynTypeDefnRepr.ObjectModel(SynTypeDefnKind.Augmentation mWithKwd, [], m), classDefns, None, m, trivia) } | typeNameInfo opt_attributes opt_access opt_HIGH_PRECEDENCE_APP opt_simplePatterns optAsSpec EQUALS tyconDefnRhsBlock - { let vis, spats, az = $3, $5, $6 + { let vis, pat, az = $3, $5, $6 let nameRange = rhs parseState 1 let (tcDefRepr, mWith, members) = $8 nameRange let (SynComponentInfo(_, _, _, lid, _, _, _, _)) = $1 @@ -1623,8 +1623,8 @@ tyconDefn: let xmlDoc = grabXmlDoc (parseState, $2, 2) let m = match lid with [] -> rhs parseState 1 | _ -> rangeOfLid lid let memberCtorPattern = - spats |> Option.map (fun spats -> - SynMemberDefn.ImplicitCtor(vis, $2, spats, Option.bind snd az, xmlDoc, m, { AsKeyword = Option.map fst az }) + pat |> Option.map (fun pat -> + SynMemberDefn.ImplicitCtor(vis, $2, pat, Option.bind snd az, xmlDoc, m, { AsKeyword = Option.map fst az }) ) let tcDefRepr = @@ -1659,16 +1659,16 @@ tyconDefn: SynTypeDefn($1, tcDefRepr, members, memberCtorPattern, mWhole, trivia) } | typeNameInfo opt_attributes opt_access opt_HIGH_PRECEDENCE_APP opt_simplePatterns optAsSpec recover - { let vis, spats, az = $3, $5, $6 + { let vis, pat, az = $3, $5, $6 let (SynComponentInfo(longId = lid)) = $1 // Gets the XML doc comments prior to the implicit constructor let xmlDoc = grabXmlDoc (parseState, $2, 2) let m = match lid with [] -> rhs parseState 1 | _ -> rangeOfLid lid let mName = $1.Range let members, mWhole = - match spats, vis, az with - | Some spats, _, _ -> - let memberCtorPattern = SynMemberDefn.ImplicitCtor(vis, $2, spats, Option.bind snd az, xmlDoc, m, { AsKeyword = Option.map fst az }) + match pat, vis, az with + | Some pat, _, _ -> + let memberCtorPattern = SynMemberDefn.ImplicitCtor(vis, $2, pat, Option.bind snd az, xmlDoc, m, { AsKeyword = Option.map fst az }) [memberCtorPattern], unionRanges mName memberCtorPattern.Range | _, _, Some(mAs, asId) -> let mAs = @@ -2716,6 +2716,16 @@ attrUnionCaseDecl: let mDecl = unionRangeWithXmlDoc xmlDoc mDecl Choice1Of2 (SynEnumCase ($1, $3, fst $5, xmlDoc, mDecl, trivia))) } + | opt_attributes opt_access unionCaseName EQUALS recover + { if Option.isSome $2 then errorR(Error(FSComp.SR.parsEnumFieldsCannotHaveVisibilityDeclarations(), rhs parseState 2)) + let mEquals = rhs parseState 4 + let expr = arbExpr ("attrUnionCaseDecl", mEquals.EndRange) + let mDecl = rhs2 parseState 1 4 + fun (xmlDoc, mBar) -> + let trivia: SynEnumCaseTrivia = { BarRange = Some mBar; EqualsRange = mEquals } + let mDecl = unionRangeWithXmlDoc xmlDoc mDecl + Choice1Of2 (SynEnumCase ($1, $3, expr, xmlDoc, mDecl, trivia)) } + /* The name of a union case */ unionCaseName: | nameop @@ -2745,6 +2755,14 @@ firstUnionCaseDeclOfMany: let mDecl = (rhs2 parseState 1 3) |> unionRangeWithXmlDoc xmlDoc Choice1Of2 (SynEnumCase ([], SynIdent($1, None), fst $3, xmlDoc, mDecl, trivia)) } + | ident EQUALS recover opt_OBLOCKSEP + { let mEquals = rhs parseState 2 + let expr = arbExpr ("firstUnionCaseDeclOfMany1", mEquals.EndRange) + let trivia: SynEnumCaseTrivia = { BarRange = None; EqualsRange = mEquals } + let xmlDoc = grabXmlDoc(parseState, [], 1) + let mDecl = (rhs2 parseState 1 2) |> unionRangeWithXmlDoc xmlDoc + Choice1Of2 (SynEnumCase ([], SynIdent($1, None), expr, xmlDoc, mDecl, trivia)) } + | firstUnionCaseDecl opt_OBLOCKSEP { $1 } @@ -2785,6 +2803,15 @@ firstUnionCaseDecl: let mDecl = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc Choice1Of2(SynEnumCase([], SynIdent($1, None), fst $3, xmlDoc, mDecl, trivia)) } + | ident EQUALS recover opt_OBLOCKSEP + { let mEquals = rhs parseState 2 + let expr = arbExpr ("firstUnionCaseDecl", mEquals.EndRange) + let trivia: SynEnumCaseTrivia = { BarRange = None; EqualsRange = mEquals } + let xmlDoc = grabXmlDoc (parseState, [], 1) + let mDecl = rhs2 parseState 1 2 |> unionRangeWithXmlDoc xmlDoc + Choice1Of2(SynEnumCase([], SynIdent($1, None), expr, xmlDoc, mDecl, trivia)) } + + unionCaseReprElements: | unionCaseReprElement STAR unionCaseReprElements { $1 :: $3 } @@ -3219,10 +3246,16 @@ localBinding: | opt_inline opt_mutable bindingPattern opt_topReturnTypeWithTypeConstraints recover { if not $5 then reportParseErrorAt (rhs parseState 5) (FSComp.SR.parsUnexpectedEndOfFileDefinition()) + let bindingPat, mBindLhs = $3 let optReturnType = $4 - let mWhole = rhs2 parseState 1 (match optReturnType with None -> 3 | _ -> 4) + let mWhole = + let mStart = rhs parseState 1 + let mEnd = + match optReturnType with + | None -> bindingPat.Range + | Some (_, returnInfo) -> returnInfo.Range + unionRanges mStart mEnd let mRhs = mWhole.EndRange // zero-width range at end of last good token - let bindingPat, mBindLhs = $3 let localBindingBuilder = (fun xmlDoc attrs vis (leadingKeyword: SynLeadingKeyword) -> let spBind = DebugPointAtBinding.Yes(unionRanges leadingKeyword.Range mRhs) @@ -3382,39 +3415,7 @@ constant: bindingPattern: | headBindingPattern - { $1, rhs parseState 1 } - -// Subset of patterns allowed to be used in implicit ctors. -// For a better error recovery we could replace these rules with the actual SynPat parsing -// and use allowed patterns only at a later analysis stage reporting errors along the way. -simplePattern: - | ident - { let m = rhs parseState 1 - SynPat.Named(SynIdent($1, None), false, None, m) } - - | QMARK ident - { SynPat.OptionalVal($2, rhs parseState 2) } - - | simplePattern COLON typeWithTypeConstraints - { SynPat.Typed($1, $3, lhs parseState) } - - | simplePattern COLON recover - { let mColon = rhs parseState 2 - let ty = SynType.FromParseError(mColon.EndRange) - SynPat.Typed($1, ty, unionRanges $1.Range mColon) } - - | attributes simplePattern %prec paren_pat_attribs - { SynPat.Attrib($2, $1, lhs parseState) } - -simplePatternCommaList: - | simplePattern - { $1 } - - | simplePattern COMMA simplePatternCommaList - { let mComma = rhs parseState 2 - match $3 with - | SynPat.Tuple(_, pats, commas, _) -> SynPat.Tuple(false, $1 :: pats, mComma :: commas, rhs2 parseState 1 3) - | _ -> SynPat.Tuple(false, [$1; $3], [mComma], rhs2 parseState 1 3) } + { $1, $1.Range } opt_simplePatterns: | simplePatterns @@ -3423,32 +3424,11 @@ opt_simplePatterns: | { None } simplePatterns: - | LPAREN simplePatternCommaList rparen - { let parenPat = SynPat.Paren($2, rhs2 parseState 1 3) - let simplePats, _ = SimplePatsOfPat parseState.SynArgNameGenerator parenPat - simplePats } + | LPAREN parenPattern rparen + { SynPat.Paren($2, rhs2 parseState 1 3) } | LPAREN rparen - { let pat = SynPat.Const(SynConst.Unit, rhs2 parseState 1 2) - let simplePats, _ = SimplePatsOfPat parseState.SynArgNameGenerator pat - simplePats } - - | LPAREN simplePatternCommaList recover - { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()) - let parenPat = SynPat.Paren(SynPat.Tuple(false, [], [], rhs2 parseState 1 2), rhs2 parseState 1 2) // todo: report parsed pats anyway? - let simplePats, _ = SimplePatsOfPat parseState.SynArgNameGenerator parenPat - simplePats } - - | LPAREN error rparen - { let parenPat = SynPat.Paren(SynPat.Wild(rhs parseState 2), rhs2 parseState 1 3) // silent recovery - let simplePats, _ = SimplePatsOfPat parseState.SynArgNameGenerator parenPat - simplePats } - - | LPAREN recover - { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()) - let pat = SynPat.Wild(lhs parseState) - let simplePats, _ = SimplePatsOfPat parseState.SynArgNameGenerator pat - simplePats } + { SynPat.Const(SynConst.Unit, rhs2 parseState 1 2) } barCanBeRightBeforeNull: | BAR @@ -3461,6 +3441,17 @@ headBindingPattern: | headBindingPattern AS constrPattern %prec AS { SynPat.As($1, $3, rhs2 parseState 1 3) } + | headBindingPattern AS recover + { let mAs = rhs parseState 2 + let pat2 = SynPat.Wild(mAs.EndRange) + SynPat.As($1, pat2, rhs2 parseState 1 2) } + + | headBindingPattern AS + { let mAs = rhs parseState 2 + reportParseErrorAt mAs (FSComp.SR.parsExpectingPattern ()) + let pat2 = SynPat.Wild(mAs.EndRange) + SynPat.As($1, pat2, rhs2 parseState 1 2) } + | headBindingPattern barCanBeRightBeforeNull headBindingPattern %prec BAR { let mBar = rhs parseState 2 SynPat.Or($1, $3, rhs2 parseState 1 3, { BarRange = mBar }) } @@ -3735,6 +3726,11 @@ parenPattern: | parenPattern AS constrPattern %prec AS { SynPat.As($1, $3, rhs2 parseState 1 3) } + | parenPattern AS recover + { let mAs = rhs parseState 2 + let pat2 = SynPat.Wild(mAs.EndRange) + SynPat.As($1, pat2, rhs2 parseState 1 2) } + | parenPattern barCanBeRightBeforeNull parenPattern %prec BAR { let mBar = rhs parseState 2 SynPat.Or($1, $3, rhs2 parseState 1 3, { BarRange = mBar }) } diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 2a8ada38b97..2090cc5883d 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -84,7 +84,7 @@ An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. - An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. + Metoda getter a setter indexované vlastnosti musí mít stejný typ. Vlastnost{0} má metodu get typu {1}, ale metodu set typu {2}. @@ -124,12 +124,12 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. - Object expressions cannot implement interfaces with static abstract members or declare static members. + Objektové výrazy nemohou implementovat rozhraní se statickými abstraktními členy ani deklarovat statické členy. The TailCall attribute should only be applied to recursive functions. - The TailCall attribute should only be applied to recursive functions. + Atribut TailCall by se měl použít jenom pro rekurzivní funkce. @@ -147,6 +147,11 @@ Dostupná přetížení:\n{0} + + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + {0} nepodporuje typ {1}, protože tento typ postrádá požadovaný (skutečný nebo vestavěný) člen {2} + + 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. @@ -274,7 +279,7 @@ Raises warnings if the 'TailCall' attribute is used on non-recursive functions. - Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Vyvolá upozornění, pokud je atribut TailCall použit u nerekurzivních funkcí. @@ -444,7 +449,7 @@ prefer extension method over plain property - prefer extension method over plain property + preferovat metodu rozšíření před prostými vlastnostmi @@ -489,7 +494,7 @@ Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type - Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type + Sdílení podkladových polí v rozlišeném sjednocení [<Struct>] za předpokladu, že mají stejný název a typ @@ -529,7 +534,7 @@ Union case test properties - Union case test properties + Vlastnosti testu případu sjednocení @@ -544,7 +549,7 @@ Indexed properties getter and setter must have the same type - Indexed properties getter and setter must have the same type + Metoda getter a setter indexované vlastnosti musí mít stejný typ. @@ -944,7 +949,7 @@ Expecting record field - Expecting record field + Očekává se pole záznamu. @@ -987,9 +992,14 @@ Tento přístup člena je nejednoznačný. Při vytváření objektu použijte závorky, např. (new SomeType(args)).MemberName' + + Only simple patterns are allowed in primary constructors + Only simple patterns are allowed in primary constructors + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. - Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. + Neúplná deklarace statického konstruktoru. Pro deklaraci použijte „static let“, „static do“, „static member“ nebo „static val“. @@ -1189,7 +1199,7 @@ Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. - Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. + Zkrácená syntaxe lambda je podporována pouze pro atomické výrazy, jako je metoda, vlastnost, pole nebo indexer v implicitní argumentu _. Příklad: let f = _. Length'. @@ -1229,7 +1239,7 @@ This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. - This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. + Toto je definice funkce, která stínuje případ sjednocení. Pokud je to to, co chcete, toto upozornění ignorujte nebo potlačte. Pokud chcete, aby se jedná o dekonstrukci případu sjednocení, přidejte závorky. @@ -1329,12 +1339,12 @@ No static abstract member was found that corresponds to this override - No static abstract member was found that corresponds to this override + Nenašla se žádný statický abstraktní člen, který by odpovídal tomuto přepsání. No static abstract property was found that corresponds to this override - No static abstract property was found that corresponds to this override + Nenašla se žádná statická abstraktní vlastnost, která by odpovídala tomuto přepsání. @@ -1434,7 +1444,7 @@ If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. - If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. + Pokud je typ sjednocení s více písmeny strukturou, musí být všechna pole se stejným názvem stejného typu. Toto pravidlo platí také pro vygenerovaný název Item v případě nepojmenovaných polí. @@ -1497,6 +1507,11 @@ Deklarování \"interfaces with static abstract methods\" (rozhraní se statickými abstraktními metodami) je pokročilá funkce. Pokyny najdete v https://aka.ms/fsharp-iwsams. Toto upozornění můžete zakázat pomocí #nowarn \"3535\" nebo '--nowarn:3535'. + + The type '{0}' has too many methods. Found: '{1}', maximum: '{2}' + Typ {0} má příliš mnoho metod. Nalezeno:{1}, maximum:{2} + + Interface member '{0}' does not have a most specific implementation. Člen rozhraní {0} nemá nejvíce specifickou implementaci. @@ -1659,7 +1674,7 @@ Parentheses can be removed. - Parentheses can be removed. + Je možné odebrat závorky. @@ -5139,7 +5154,7 @@ For F#7 and lower, static 'let','do' and 'member val' definitions may only be used in types with a primary constructor ('type X(args) = ...'). To enable them in all other types, use language version '8' or higher. - Pro F#7 a nižší se definice statických hodnot dají použít jenom v typech s primárním konstruktorem ('type X(args) = ...'). Pokud je chcete povolit ve všech ostatních typech, použijte jazykovou verzi „preview“. + Pro definice F#7 a nižší, „static let“, „do“ a „member val“ lze použít pouze v typech s primárním konstruktorem (typ X(args) = ...). Pokud je chcete povolit ve všech ostatních typech, použijte jazyk verze 8 nebo vyšší. @@ -8544,7 +8559,7 @@ Cannot call the byref extension method '{0}. 'this' parameter requires the value to be mutable or a non-readonly byref type. - Nejde volat metodu rozšíření byref {0}. První parametr vyžaduje, aby hodnota byla měnitelná nebo typu byref, která není jen pro čtení. + Nejde volat metodu rozšíření byref {0}. Parametr „this“ vyžaduje, aby hodnota byla měnitelná nebo typu byref, která není jen pro čtení. @@ -8634,7 +8649,7 @@ Package manager key '{0}' was not registered in {1}. Currently registered: {2}. You can provide extra path(s) by passing '--compilertool:<extensionsfolder>' to the command line. To learn more about extensions, visit: https://aka.ms/dotnetdepmanager - Klíč správce balíčků „{0}“ nebyl v {1} zaregistrován. Aktuálně zaregistrováno: {2}. Další informace o rozšířeních najdete tady: https://aka.ms/dotnetdepmanager + Klíč správce balíčků „{0}“ nebyl v {1} zaregistrován. Aktuálně zaregistrováno: {2}. Cesty navíc můžete zadat tak, že do příkazového řádku předáte --compilertool:<extensionsfolder>. Další informace o rozšířeních najdete tady: https://aka.ms/dotnetdepmanager diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index d62f45e4cd7..8457960a3b0 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -84,7 +84,7 @@ An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. - An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. + Getter und Setter einer indizierten Eigenschaft müssen denselben Typ aufweisen. Eigenschaft "{0}" hat einen Getter vom Typ "{1}", jedoch einen Setter vom Typ "{2}". @@ -124,12 +124,12 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. - Object expressions cannot implement interfaces with static abstract members or declare static members. + Objektausdrücke können keine Schnittstellen mit statischen abstrakten Membern implementieren oder statische Member deklarieren. The TailCall attribute should only be applied to recursive functions. - The TailCall attribute should only be applied to recursive functions. + Das Attribut "TailCall" darf nur auf rekursive Funktionen angewendet werden. @@ -147,6 +147,11 @@ Verfügbare Überladungen:\n{0} + + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + "{0}" unterstützt den Typ "{1}" nicht, da letzteres nicht das erforderliche (echte oder integrierte) Element "{2}" aufweist. + + 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. @@ -274,7 +279,7 @@ Raises warnings if the 'TailCall' attribute is used on non-recursive functions. - Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Löst Warnungen aus, wenn das Attribut "TailCall" für nicht rekursive Funktionen verwendet wird. @@ -444,7 +449,7 @@ prefer extension method over plain property - prefer extension method over plain property + Erweiterungsmethode gegenüber plain-Eigenschaft bevorzugen @@ -489,7 +494,7 @@ Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type - Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type + Teilen sie zugrunde liegende Felder in einen [<Struct>]-diskriminierten Union, solange sie denselben Namen und Typ aufweisen. @@ -529,7 +534,7 @@ Union case test properties - Union case test properties + Eigenschaften von Union-Falltests @@ -544,7 +549,7 @@ Indexed properties getter and setter must have the same type - Indexed properties getter and setter must have the same type + Getter und Setter für indizierte Eigenschaften müssen denselben Typ aufweisen. @@ -944,7 +949,7 @@ Expecting record field - Expecting record field + Datensatzfeld wird erwartet @@ -987,9 +992,14 @@ Dieser Memberzugriff ist mehrdeutig. Setzen Sie Klammern um die Objekterstellung, z. B. "(new SomeType(args)). MemberName“ + + Only simple patterns are allowed in primary constructors + Only simple patterns are allowed in primary constructors + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. - Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. + Unvollständige Deklaration eines statischen Konstrukts. Verwenden Sie "static let", "static do", "static member" oder "static val" für die Deklaration. @@ -1189,7 +1199,7 @@ Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. - Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. + Die Lambdasyntax der Kurzform wird nur für atomische Ausdrücke wie Methode, Eigenschaft, Feld oder Indexer für das implizite Argument "_" unterstützt. Beispiel: "let f = _. Länge". @@ -1229,7 +1239,7 @@ This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. - This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. + Dies ist eine Funktionsdefinition, die einen Union-Fall überschatten kann. Wenn Sie dies wünschen, ignorieren oder unterdrücken Sie diese Warnung. Wenn es sich um eine Dekonstruktion des Union-Falls handelt, fügen Sie Klammern hinzu. @@ -1329,12 +1339,12 @@ No static abstract member was found that corresponds to this override - No static abstract member was found that corresponds to this override + Es wurde kein abstrakter Member gefunden, der dieser Überschreibung entspricht. No static abstract property was found that corresponds to this override - No static abstract property was found that corresponds to this override + Es wurde keine statische abstrakte Eigenschaft gefunden, die dieser Überschreibung entspricht. @@ -1434,7 +1444,7 @@ If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. - If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. + Wenn ein Union-Typ mit mehreren Großbuchstaben eine Struktur ist, müssen alle Felder mit demselben Namen denselben Typ aufweisen. Diese Regel gilt auch für den generierten Elementnamen bei unbenannten Feldern. @@ -1497,6 +1507,11 @@ Das Deklarieren von \"Schnittstellen mit statischen abstrakten Methoden\" ist ein erweitertes Feature. Anleitungen finden Sie unter https://aka.ms/fsharp-iwsams. Sie können diese Warnung deaktivieren, indem Sie „#nowarn \"3535\"“ or „--nowarn:3535“ verwenden. + + The type '{0}' has too many methods. Found: '{1}', maximum: '{2}' + Der Typ "{0}" weist zu viele Methoden auf. Gefunden: "{1}", Maximum: "{2}" + + Interface member '{0}' does not have a most specific implementation. Der Schnittstellenmember "{0}" weist keine spezifischste Implementierung auf. @@ -1659,7 +1674,7 @@ Parentheses can be removed. - Parentheses can be removed. + Klammern können entfernt werden. @@ -5139,7 +5154,7 @@ For F#7 and lower, static 'let','do' and 'member val' definitions may only be used in types with a primary constructor ('type X(args) = ...'). To enable them in all other types, use language version '8' or higher. - Für F# 7 und früher dürfen statische Wertdefinitionen nur in Typen mit einem primären Konstruktor verwendet werden (type X(args) = ...). Um sie in anderen Typen zu aktivieren, verwenden Sie die Sprachversion "preview". + Für F# 7 und früher dürfen die statische Definitionen "let", "do" und "member" nur in Typen mit einem primären Konstruktor verwendet werden (type X(args) = ...). Um sie in anderen Typen zu aktivieren, verwenden Sie die Sprachversion "8" oder höher. @@ -8544,7 +8559,7 @@ Cannot call the byref extension method '{0}. 'this' parameter requires the value to be mutable or a non-readonly byref type. - Die ByRef-Erweiterungsmethode "{0}" kann nicht aufgerufen werden. Für den ersten Parameter muss der Wert änderbar sein oder einem nicht schreibgeschützten ByRef-Typ entsprechen. + Die ByRef-Erweiterungsmethode "{0}" kann nicht aufgerufen werden. Für den Parameter „this“ muss der Wert änderbar sein oder einem nicht schreibgeschützten ByRef-Typ entsprechen. @@ -8634,7 +8649,7 @@ Package manager key '{0}' was not registered in {1}. Currently registered: {2}. You can provide extra path(s) by passing '--compilertool:<extensionsfolder>' to the command line. To learn more about extensions, visit: https://aka.ms/dotnetdepmanager - Der Paket-Manager-Schlüssel "{0}" wurde nicht in "{1}" registriert. Zurzeit registriert: {2}. Weitere Informationen zu Erweiterungen finden Sie unter: https://aka.ms/dotnetdepmanager + Der Paket-Manager-Schlüssel "{0}" wurde nicht in "{1}" registriert. Zurzeit registriert: {2}. Sie können zusätzliche Pfade angeben, indem Sie "--compilertool:<extensionsfolder>" an die Befehlszeile übergeben. Weitere Informationen zu Erweiterungen finden Sie unter: https://aka.ms/dotnetdepmanager diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 08bf1b59b23..02c83adf195 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -84,7 +84,7 @@ An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. - An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. + El captador y el establecedor de una propiedad indexada deben tener el mismo tipo. La propiedad '{0}' tiene un captador de tipo '{1}', pero el establecedor es de tipo '{2}'. @@ -124,12 +124,12 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. - Object expressions cannot implement interfaces with static abstract members or declare static members. + Las expresiones de objeto no pueden implementar interfaces con miembros abstractos estáticos ni declarar miembros estáticos. The TailCall attribute should only be applied to recursive functions. - The TailCall attribute should only be applied to recursive functions. + El atributo TailCall solo se debe aplicar a funciones recursivas. @@ -147,6 +147,11 @@ Sobrecargas disponibles:\n{0} + + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' no admite el tipo '{1}', porque a este último le falta el '{2}' de miembro necesario (real o integrado) + + 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. @@ -274,7 +279,7 @@ Raises warnings if the 'TailCall' attribute is used on non-recursive functions. - Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Genera advertencias si el atributo 'TailCall' se usa en funciones no recursivas. @@ -444,7 +449,7 @@ prefer extension method over plain property - prefer extension method over plain property + preferir método de extensión sobre propiedad sin formato @@ -489,7 +494,7 @@ Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type - Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type + Compartir campos subyacentes en una unión discriminada [<Struct>] siempre y cuando tengan el mismo nombre y tipo @@ -529,7 +534,7 @@ Union case test properties - Union case test properties + Propiedades de prueba de caso de unión @@ -544,7 +549,7 @@ Indexed properties getter and setter must have the same type - Indexed properties getter and setter must have the same type + El captador y el establecedor de propiedades indexadas deben tener el mismo tipo. @@ -944,7 +949,7 @@ Expecting record field - Expecting record field + Se espera un campo de registro @@ -987,9 +992,14 @@ Este acceso de miembro es ambiguo. Use paréntesis alrededor de la creación del objeto, por ejemplo, '(nuevo AlgúnTipo(args)).NombreMiembro' + + Only simple patterns are allowed in primary constructors + Only simple patterns are allowed in primary constructors + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. - Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. + Declaración incompleta de una construcción estática. Use "static let", "static do", "static member" o "static val" para la declaración. @@ -1189,7 +1199,7 @@ Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. - Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. + La sintaxis lambda abreviada solo se admite para expresiones atómicas, como el método, la propiedad, el campo o el indexador en el argumento '_' implícito. Por ejemplo: 'let f = _.Length'. @@ -1229,7 +1239,7 @@ This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. - This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. + Esta es una definición de función que oculta un caso de unión. Si esto es lo que desea, omita o suprima esta advertencia. Si desea que sea una desconstrucción de caso de unión, agregue paréntesis. @@ -1329,12 +1339,12 @@ No static abstract member was found that corresponds to this override - No static abstract member was found that corresponds to this override + No se encontró ningún miembro abstracto estático que corresponda a esta invalidación. No static abstract property was found that corresponds to this override - No static abstract property was found that corresponds to this override + No se encontró ninguna propiedad abstracta estática que corresponda a esta invalidación. @@ -1434,7 +1444,7 @@ If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. - If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. + Si un tipo de unión multicase es un struct, todos los campos con el mismo nombre deben ser del mismo tipo. Esta regla se aplica también al nombre "Item" generado en el caso de campos sin nombre. @@ -1497,6 +1507,11 @@ Declarar \"interfaces con métodos abstractos estáticos\" es una característica avanzada. Consulte https://aka.ms/fsharp-iwsams para obtener instrucciones. Puede deshabilitar esta advertencia con "#nowarn \"3535\"" o "--nowarn:3535". + + The type '{0}' has too many methods. Found: '{1}', maximum: '{2}' + El tipo '{0}' tiene demasiados métodos. Encontrado: '{1}', máximo: '{2}' + + Interface member '{0}' does not have a most specific implementation. El miembro de interfaz "{0}" no tiene una implementación más específica. @@ -1659,7 +1674,7 @@ Parentheses can be removed. - Parentheses can be removed. + Los paréntesis se pueden quitar. @@ -5139,7 +5154,7 @@ For F#7 and lower, static 'let','do' and 'member val' definitions may only be used in types with a primary constructor ('type X(args) = ...'). To enable them in all other types, use language version '8' or higher. - Para F#7 y versiones anteriores, las definiciones de valores estáticos solo se pueden usar en tipos con un constructor principal ('type X(args) = ...'). Para habilitarlos en todos los demás tipos, use la versión de idioma "preview". + Para F#7 y versiones anteriores, las definiciones estáticas 'let','do' y 'member val' solo se pueden usar en tipos con un constructor principal ('type X(args) = ...'). Para habilitarlos en todos los demás tipos, use la versión de idioma "8" o una versión posterior. @@ -8544,7 +8559,7 @@ Cannot call the byref extension method '{0}. 'this' parameter requires the value to be mutable or a non-readonly byref type. - No se puede llamar al método de extensión de byref "{0}". El primer parámetro requiere que el valor sea mutable o un tipo de byref que no sea de solo lectura. + No se puede llamar al método de extensión de byref "{0}". El parámetro 'this' requiere que el valor sea mutable o un tipo byref no de solo lectura. @@ -8634,7 +8649,7 @@ Package manager key '{0}' was not registered in {1}. Currently registered: {2}. You can provide extra path(s) by passing '--compilertool:<extensionsfolder>' to the command line. To learn more about extensions, visit: https://aka.ms/dotnetdepmanager - La clave del administrador de paquetes "{0}" no se registró en {1}. Registrado actualmente: {2}. Para obtener más información sobre las extensiones, visite https://aka.ms/dotnetdepmanager + La clave del administrador de paquetes "{0}" no se registró en {1}. Registrado actualmente: {2}. Puede proporcionar rutas adicionales pasando '--compilertool:<extensionsfolder>' a la línea de comando. Para obtener más información sobre las extensiones, visite https://aka.ms/dotnetdepmanager diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 5089523c330..7680237f22d 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -84,7 +84,7 @@ An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. - An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. + Les méthodes getter et setter d’une propriété indexée doivent avoir le même type. La propriété « {0} » a une méthode getter de type « {1} » alors que sa méthode setter est de type « {2} ». @@ -124,12 +124,12 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. - Object expressions cannot implement interfaces with static abstract members or declare static members. + Les expressions d’objet ne peuvent pas implémenter des interfaces avec des membres abstraits statiques ou déclarer des membres statiques. The TailCall attribute should only be applied to recursive functions. - The TailCall attribute should only be applied to recursive functions. + L’attribut TailCall ne doit être appliqué qu’aux fonctions récursives. @@ -147,6 +147,11 @@ Surcharges disponibles :\n{0} + + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' ne prend pas en charge le type '{1}', car ce dernier n'a pas le membre requis (réel ou intégré) '{2}' + + 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. @@ -274,7 +279,7 @@ Raises warnings if the 'TailCall' attribute is used on non-recursive functions. - Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Émet des avertissements si l’attribut « TailCall » est utilisé sur des fonctions non récursives. @@ -444,7 +449,7 @@ prefer extension method over plain property - prefer extension method over plain property + préférer la méthode d’extension à la propriété simple @@ -489,7 +494,7 @@ Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type - Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type + Partager les champs sous-jacents dans une union discriminée [<Struct>] tant qu’ils ont le même nom et le même type @@ -529,7 +534,7 @@ Union case test properties - Union case test properties + Propriétés du test de cas d’union @@ -544,7 +549,7 @@ Indexed properties getter and setter must have the same type - Indexed properties getter and setter must have the same type + Les propriétés indexées getter et setter doivent avoir le même type @@ -944,7 +949,7 @@ Expecting record field - Expecting record field + Champ d’enregistrement attendu @@ -987,9 +992,14 @@ L’accès à ce membre est ambigu. Utilisez des parenthèses autour de la création de l’objet, par exemple' (New SomeType (args)). MemberName + + Only simple patterns are allowed in primary constructors + Only simple patterns are allowed in primary constructors + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. - Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. + Déclaration incomplète d’une construction statique. Utilisez « static let », « static do », « static member » ou « static val » pour la déclaration. @@ -1189,7 +1199,7 @@ Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. - Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. + La syntaxe lambda raccourcie est prise en charge uniquement pour les expressions atomiques, telles que la méthode, la propriété, le champ ou l’indexeur sur l’argument ’_’ implicite. Par exemple : « let f = _. Longueur ». @@ -1229,7 +1239,7 @@ This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. - This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. + Il s’agit d’une définition de fonction qui masque un cas d’union. Si c’est ce que vous voulez, ignorez ou supprimez cet avertissement. Si vous voulez qu’il s’agit d’une déconstruction de cas d’union, ajoutez des parenthèses. @@ -1329,12 +1339,12 @@ No static abstract member was found that corresponds to this override - No static abstract member was found that corresponds to this override + Désolé, nous n’avons pas pu trouver un membre abstrait statique qui corresponde à cette substitution No static abstract property was found that corresponds to this override - No static abstract property was found that corresponds to this override + Désolé, nous n’avons pas pu trouver une propriété abstraite statique qui corresponde à cette substitution @@ -1434,7 +1444,7 @@ If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. - If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. + Si un type union multicase est un struct, tous les champs portant le même nom doivent être du même type. Cette règle s’applique également au nom « Item » généré en cas de champs sans nom. @@ -1497,6 +1507,11 @@ La déclaration de \"interfaces with static abstract methods\" est une fonctionnalité avancée. Consultez https://aka.ms/fsharp-iwsams pour obtenir de l’aide. Vous pouvez désactiver cet avertissement à l’aide de '#nowarn \"3535\"' or '--nowarn:3535'. + + The type '{0}' has too many methods. Found: '{1}', maximum: '{2}' + Le type '{0}' a trop de méthodes. Trouvé : '{1}', maximum : '{2}' + + Interface member '{0}' does not have a most specific implementation. Le membre d'interface '{0}' n'a pas l'implémentation la plus spécifique. @@ -1659,7 +1674,7 @@ Parentheses can be removed. - Parentheses can be removed. + Vous pouvez supprimer les parenthèses. @@ -5139,7 +5154,7 @@ For F#7 and lower, static 'let','do' and 'member val' definitions may only be used in types with a primary constructor ('type X(args) = ...'). To enable them in all other types, use language version '8' or higher. - Pour F#7 et versions antérieures, les définitions de valeurs statiques ne peuvent être utilisées que dans les types avec un constructeur principal (« type X(args) = ... »). Pour les activer dans tous les autres types, utilisez la version linguistique « aperçu ». + Pour les définitions F#7 et inférieures, les définitions statiques « let », « do » et « member val » ne peuvent être utilisées que dans les types avec un constructeur principal (« type X(args) = ... »). Pour les activer dans tous les autres types, utilisez la version linguistique « 8 » ou ultérieure. @@ -8544,7 +8559,7 @@ Cannot call the byref extension method '{0}. 'this' parameter requires the value to be mutable or a non-readonly byref type. - Impossible d’appeler la méthode d’extension byref « {0} ». Le premier paramètre nécessite que la valeur soit mutable ou un type byref autre qu'en lecture seule. + Impossible d’appeler la méthode d’extension byref '{0}. Le paramètre 'this' nécessite que la valeur soit mutable ou un type byref non readonly. @@ -8634,7 +8649,7 @@ Package manager key '{0}' was not registered in {1}. Currently registered: {2}. You can provide extra path(s) by passing '--compilertool:<extensionsfolder>' to the command line. To learn more about extensions, visit: https://aka.ms/dotnetdepmanager - La clé du gestionnaire de packages « {0} » n'a pas été enregistrée dans {1}. Actuellement inscrit : {2}. Pour en savoir plus sur les extensions, visitez : https://aka.ms/dotnetdepmanager + La clé du gestionnaire de package «{0}» n’a pas été inscrite dans {1}. Actuellement inscrit : {2}. Vous pouvez fournir des chemins d’accès supplémentaires en passant « --compilertool :<extensionsfolder> » à la ligne de commande. Pour en savoir plus sur les extensions, consultez : https://aka.ms/dotnetdepmanager diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index cdc2dd7ac91..af598a60a92 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -84,7 +84,7 @@ An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. - An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. + Il getter e il setter di una proprietà indicizzata devono essere dello stesso tipo. Il getter della proprietà '{0}' è di tipo '{1}', mentre il setter è di tipo '{2}'. @@ -124,12 +124,12 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. - Object expressions cannot implement interfaces with static abstract members or declare static members. + Le espressioni di oggetto non possono implementare interfacce con membri astratti statici o dichiarare membri statici. The TailCall attribute should only be applied to recursive functions. - The TailCall attribute should only be applied to recursive functions. + L'attributo TailCall deve essere applicato solo a funzioni ricorsive. @@ -147,6 +147,11 @@ Overload disponibili:\n{0} + + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' non supporta il tipo '{1}', perché in quest'ultimo manca il membro '{2}' richiesto (reale o predefinito) + + 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. @@ -274,7 +279,7 @@ Raises warnings if the 'TailCall' attribute is used on non-recursive functions. - Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Genera avvisi se l'attributo 'TailCall' viene utilizzato in funzioni non ricorsive. @@ -444,7 +449,7 @@ prefer extension method over plain property - prefer extension method over plain property + preferisci il metodo di estensione alla proprietà normale @@ -489,7 +494,7 @@ Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type - Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type + Condividi i campi sottostanti in un'unione discriminata di [<Struct>] purché abbiano lo stesso nome e tipo @@ -529,7 +534,7 @@ Union case test properties - Union case test properties + Proprietà test case di unione @@ -544,7 +549,7 @@ Indexed properties getter and setter must have the same type - Indexed properties getter and setter must have the same type + Il getter e il setter delle proprietà indicizzate devono avere lo stesso tipo @@ -944,7 +949,7 @@ Expecting record field - Expecting record field + Previsto campo record @@ -987,9 +992,14 @@ L'accesso ai membri è ambiguo. Utilizzare le parentesi intorno alla creazione oggetto, ad esempio “(New SomeType (args)). MemberName” + + Only simple patterns are allowed in primary constructors + Only simple patterns are allowed in primary constructors + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. - Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. + Dichiarazione incompleta di un costrutto statico. Usare 'static let','static do','static member' o 'static val' per la dichiarazione. @@ -1189,7 +1199,7 @@ Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. - Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. + La sintassi lambda a sintassi abbreviata è supportata solo per le espressioni atomiche, ad esempio metodo, proprietà, campo o indicizzatore nell'argomento '_' implicito. Ad esempio: 'let f = _. Lunghezza'. @@ -1229,7 +1239,7 @@ This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. - This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. + Definizione di funzione che nasconde un case di unione. Se si desidera eseguire questa operazione, ignorare o eliminare questo avviso. Se si desidera che sia una decostruzione di case di unione, aggiungere le parentesi. @@ -1329,12 +1339,12 @@ No static abstract member was found that corresponds to this override - No static abstract member was found that corresponds to this override + Nessun membro astratto statico trovato corrispondente all'override No static abstract property was found that corresponds to this override - No static abstract property was found that corresponds to this override + Nessuna proprietà astratta statica trovata corrispondente all'override @@ -1434,7 +1444,7 @@ If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. - If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. + Se un tipo di unione multicase è uno struct, tutti i campi con lo stesso nome devono essere dello stesso tipo. Questa regola si applica anche al nome 'Elemento' generato in caso di campi senza nome. @@ -1497,6 +1507,11 @@ La dichiarazione di \"interfaces with static abstract methods\" è una funzionalità avanzata. Per indicazioni, vedere https://aka.ms/fsharp-iwsams. È possibile disabilitare questo avviso usando '#nowarn \"3535\"' o '--nowarn:3535'. + + The type '{0}' has too many methods. Found: '{1}', maximum: '{2}' + Il tipo '{0}' contiene troppi metodi. Trovato: '{1}', massimo: '{2}' + + Interface member '{0}' does not have a most specific implementation. Il membro di interfaccia '{0}' non contiene un'implementazione più specifica. @@ -1659,7 +1674,7 @@ Parentheses can be removed. - Parentheses can be removed. + È possibile rimuovere le parentesi. @@ -5139,7 +5154,7 @@ For F#7 and lower, static 'let','do' and 'member val' definitions may only be used in types with a primary constructor ('type X(args) = ...'). To enable them in all other types, use language version '8' or higher. - Per F#7 e versioni precedenti, le definizioni di valori statici possono essere usate solo in tipi con un costruttore primario ('type X(args) = ...'). Per abilitarli in tutti gli altri tipi, usare la versione di "anteprima" del linguaggio. + Per F#7 e versioni precedenti, le definizioni di valori statici 'let','do' e 'member val' possono essere usate solo in tipi con un costruttore primario ('type X(args) = ...'). Per abilitarli in tutti gli altri tipi, usare la versione del linguaggio '8' o successiva. @@ -8544,7 +8559,7 @@ Cannot call the byref extension method '{0}. 'this' parameter requires the value to be mutable or a non-readonly byref type. - Non è possibile chiamare il metodo di estensione byref '{0}. Il valore del primo parametro deve essere modificabile oppure un tipo byref non di sola lettura. + Non è possibile chiamare il metodo di estensione byref '{0}. ‘questo parametro deve essere modificabile oppure un tipo byref non di sola lettura. @@ -8634,7 +8649,7 @@ Package manager key '{0}' was not registered in {1}. Currently registered: {2}. You can provide extra path(s) by passing '--compilertool:<extensionsfolder>' to the command line. To learn more about extensions, visit: https://aka.ms/dotnetdepmanager - La chiave "'{0}" del gestione pacchetti non è stata registrata in {1}. Attualmente registrata: {2}. Per altre informazioni sulle estensioni, vedere: https://aka.ms/dotnetdepmanager + La chiave "'{0}" del gestione pacchetti non è stata registrata in {1}. Attualmente registrata: {2}. Per fornire percorsi aggiuntivi, passare '--compilertool:<extensionsfolder>' alla riga di comando. Per altre informazioni sulle estensioni, vedere: https://aka.ms/dotnetdepmanager diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index bbc8b647621..da6e725af01 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -84,7 +84,7 @@ An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. - An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. + インデックスの付いたプロパティのゲッターとセッターは同じ型でなければなりません。プロパティ '{0}' は、ゲッターの型が '{1}' ですが、セッターの型は '{2}' です。 @@ -124,12 +124,12 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. - Object expressions cannot implement interfaces with static abstract members or declare static members. + オブジェクト式は、静的抽象メンバーを持つインターフェイスを実装したり、静的メンバーを宣言したりすることはできません。 The TailCall attribute should only be applied to recursive functions. - The TailCall attribute should only be applied to recursive functions. + TailCall 属性は再帰関数にのみ適用する必要があります。 @@ -147,6 +147,11 @@ 使用可能なオーバーロード:\n{0} + + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + 型 '{1}' には必要な (実数または組み込み) メンバー '{2}' がないため、'{0}' ではサポートされません + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. ジェネリック コンストラクトでは、ジェネリック型パラメーターが構造体または参照型として認識されている必要があります。型の注釈の追加を検討してください。 @@ -274,7 +279,7 @@ Raises warnings if the 'TailCall' attribute is used on non-recursive functions. - Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + 'TailCall' 属性が再帰関数以外で使用されている場合、警告が発せられます。 @@ -444,7 +449,7 @@ prefer extension method over plain property - prefer extension method over plain property + plain プロパティよりも拡張メソッドを優先する @@ -489,7 +494,7 @@ Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type - Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type + 名前と型が同じである限り、[<Struct>] 判別可能な共用体で基になるフィールドを共有する @@ -529,7 +534,7 @@ Union case test properties - Union case test properties + ユニオン ケースのテスト プロパティ @@ -544,7 +549,7 @@ Indexed properties getter and setter must have the same type - Indexed properties getter and setter must have the same type + インデックス付きプロパティのゲッターとセッターの型は同じである必要があります @@ -944,7 +949,7 @@ Expecting record field - Expecting record field + レコード フィールドが必要です @@ -987,9 +992,14 @@ このメンバーへのアクセスはあいまいです。オブジェクト作成の前後にはかっこを使用してください。例: '(new SomeType(args)).MemberName' + + Only simple patterns are allowed in primary constructors + Only simple patterns are allowed in primary constructors + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. - Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. + 静的コンストラクトの不完全な宣言。宣言には、'static let'、'static do'、'static member'、または 'static val' を使用します。 @@ -1189,7 +1199,7 @@ Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. - Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. + 短縮ラムダ構文は、暗黙的な '_' 引数のメソッド、プロパティ、フィールド、インデクサーなどのアトミック式でのみサポートされています。例: 'let f = _.Length'。 @@ -1229,7 +1239,7 @@ This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. - This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. + これは、共用体のケースをシャドウする関数定義です。これが必要な場合は、この警告を無視するか、非表示にしてください。共用体のケース分解にする場合は、かっこを追加します。 @@ -1329,12 +1339,12 @@ No static abstract member was found that corresponds to this override - No static abstract member was found that corresponds to this override + このオーバーライドに対応する静的抽象メンバーが見つかりませんでした No static abstract property was found that corresponds to this override - No static abstract property was found that corresponds to this override + このオーバーライドに対応する抽象プロパティが見つかりませんでした @@ -1434,7 +1444,7 @@ If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. - If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. + マルチケース共用体型が構造体の場合、同じ名前を持つすべてのフィールドが同じ型である必要があります。このルールは、名前のないフィールドの場合に生成された 'Item' 名にも適用されます。 @@ -1497,6 +1507,11 @@ \"interfaces with static abstract method\" の宣言は高度な機能です。ガイダンスについては https://aka.ms/fsharp-iwsams を参照してください。この警告は、'#nowarn \"3535\"' または '--nowarn:3535' を使用して無効にできます。 + + The type '{0}' has too many methods. Found: '{1}', maximum: '{2}' + 型 '{0}' に含まれるメソッドが多すぎます。検出した内容: '{1}'、最大値: '{2}' + + Interface member '{0}' does not have a most specific implementation. インターフェイス メンバー '{0}' には最も固有な実装がありません。 @@ -1659,7 +1674,7 @@ Parentheses can be removed. - Parentheses can be removed. + かっこは削除できます。 @@ -5139,7 +5154,7 @@ For F#7 and lower, static 'let','do' and 'member val' definitions may only be used in types with a primary constructor ('type X(args) = ...'). To enable them in all other types, use language version '8' or higher. - F#7 以前の場合、静的な値の定義は、プライマリ コンストラクター ('type X(args) = ...') を持つ型でのみ使用できます。他のすべての種類で有効にするには、言語バージョン 'preview' を使用します。 + F#7 以前の場合、静的な 'let'、'do'、'member val' の定義は、プライマリ コンストラクター ('type X(args) = ...') を持つ型でのみ使用できます。他のすべての型で有効にするには、言語バージョン '8' 以降を使用します。 @@ -8544,7 +8559,7 @@ Cannot call the byref extension method '{0}. 'this' parameter requires the value to be mutable or a non-readonly byref type. - byref 拡張メソッド '{0} を呼び出すことはできません。最初のパラメーターでは、値を変更可能な byref 型または読み取り専用以外の byref 型にする必要があります。 + byref 拡張メソッド '{0}を呼び出すことはできません。'this' パラメーターには、値を変更可能にするか、読み取り専用以外の byref 型を指定する必要があります。 @@ -8634,7 +8649,7 @@ Package manager key '{0}' was not registered in {1}. Currently registered: {2}. You can provide extra path(s) by passing '--compilertool:<extensionsfolder>' to the command line. To learn more about extensions, visit: https://aka.ms/dotnetdepmanager - パッケージ マネージャー キー '{0}' は {1} に登録されませんでした。現在登録済み: {2}。拡張機能の詳細については、次を参照してください: https://aka.ms/dotnetdepmanager + パッケージ マネージャー キー '{0}' は {1} に登録されませんでした。現在登録されているもの: {2}。'--compilertool:<extensionsfolder>' をコマンド ラインに渡すことで、追加のパスを指定できます。拡張機能の詳細については、次を参照してください: https://aka.ms/dotnetdepmanager diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index ca0ca6e940f..be43787c542 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -84,7 +84,7 @@ An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. - An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. + 인덱싱된 속성의 getter와 setter의 형식이 같아야 합니다. '{0}' 속성에 '{1}' 형식의 getter가 있지만 '{2}’ 형식의 setter가 있습니다. @@ -124,12 +124,12 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. - Object expressions cannot implement interfaces with static abstract members or declare static members. + 개체 식은 정적 추상 멤버가 있는 인터페이스를 구현하거나 정적 멤버를 선언할 수 없습니다. The TailCall attribute should only be applied to recursive functions. - The TailCall attribute should only be applied to recursive functions. + TailCall 특성은 재귀 함수에만 적용해야 합니다. @@ -147,6 +147,11 @@ 사용 가능한 오버로드:\n{0} + + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{1}' 형식에는 필수(실제 또는 기본 제공) 멤버 '{2}'이(가) 없기 때문에 '{0}'이(가) 이 형식을 지원하지 않습니다. + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. 제네릭 구문을 사용하려면 구조체 또는 참조 형식의 제네릭 형식 매개 변수가 필요합니다. 형식 주석을 추가하세요. @@ -274,7 +279,7 @@ Raises warnings if the 'TailCall' attribute is used on non-recursive functions. - Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + 'TailCall' 특성이 비 재귀 함수에 사용되는 경우 경고를 발생합니다. @@ -444,7 +449,7 @@ prefer extension method over plain property - prefer extension method over plain property + 일반 속성보다 확장 메서드 선호 @@ -489,7 +494,7 @@ Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type - Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type + 이름과 형식이 같으면 [<Struct>] 구분된 공용 구조체에서 기본 필드 공유 @@ -529,7 +534,7 @@ Union case test properties - Union case test properties + 공용 구조체 사례 테스트 속성 @@ -544,7 +549,7 @@ Indexed properties getter and setter must have the same type - Indexed properties getter and setter must have the same type + 인덱싱된 속성 getter와 setter의 형식이 같아야 합니다. @@ -944,7 +949,7 @@ Expecting record field - Expecting record field + 레코드 필드 필요 @@ -987,9 +992,14 @@ 이 구성원 액세스가 모호합니다. 개체 생성 주위에 괄호를 사용하세요. 예: '(새로운 SomeType(인수)).MemberName' + + Only simple patterns are allowed in primary constructors + Only simple patterns are allowed in primary constructors + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. - Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. + 정적 구문의 선언이 불완전합니다. 선언에 'static let','static do','static member' 또는 'static val'을 사용합니다. @@ -1189,7 +1199,7 @@ Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. - Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. + 줄임 람다 구문은 암시적 '_' 인수의 메서드, 속성, 필드 또는 인덱서와 같은 원자성 식에 대해서만 지원됩니다. 예: 'let f = _.Length'. @@ -1229,7 +1239,7 @@ This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. - This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. + 공용 구조체 케이스를 음영 처리하는 함수입니다. 원하는 경우 이 경고를 무시하거나 표시하지 않습니다. 공용 구조체 케이스 분해가 되도록 하려면 괄호를 추가합니다. @@ -1329,12 +1339,12 @@ No static abstract member was found that corresponds to this override - No static abstract member was found that corresponds to this override + 이 재정의에 해당하는 정적 추상 멤버를 찾을 수 없습니다. No static abstract property was found that corresponds to this override - No static abstract property was found that corresponds to this override + 이 재정의에 해당하는 정적 추상 속성을 찾을 수 없습니다. @@ -1434,7 +1444,7 @@ If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. - If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. + 멀티캐시 공용 구조체 형식이 구조체이면 이름이 같은 모든 필드의 형식이 같아야 합니다. 이 규칙은 명명되지 않은 필드의 경우 생성된 '항목' 이름에도 적용됩니다. @@ -1497,6 +1507,11 @@ \"interfaces with static abstract methods\"를 선언하는 것은 고급 기능입니다. 지침은 https://aka.ms/fsharp-iwsams를 참조하세요. '#nowarn \"3535\"' 또는 '--nowarn:3535'를 사용하여 이 경고를 비활성화할 수 있습니다. + + The type '{0}' has too many methods. Found: '{1}', maximum: '{2}' + '{0}' 형식에 메서드가 너무 많습니다. 찾은 항목: '{1}', 최대: '{2}' + + Interface member '{0}' does not have a most specific implementation. 인터페이스 멤버 '{0}'에 가장 한정적인 구현이 없습니다. @@ -1659,7 +1674,7 @@ Parentheses can be removed. - Parentheses can be removed. + 괄호를 제거할 수 있습니다. @@ -5139,7 +5154,7 @@ For F#7 and lower, static 'let','do' and 'member val' definitions may only be used in types with a primary constructor ('type X(args) = ...'). To enable them in all other types, use language version '8' or higher. - F#7 이하의 경우 정적 값 정의는 기본 생성자('type X(args) = ...')가 있는 형식에서만 사용할 수 있습니다. 다른 모든 형식에서 사용하도록 설정하려면 언어 버전 '미리 보기'를 사용합니다. + F#7 이하의 경우, 정적 'let', 'do' 및 'member val' 정의는 기본 생성자가 있는 타입('type X(args) = ...')에서만 사용할 수 있습니다. 다른 모든 형식에서 사용하도록 설정하려면 언어 버전 ‘8’ 또는 그 이상을 사용합니다. @@ -8544,7 +8559,7 @@ Cannot call the byref extension method '{0}. 'this' parameter requires the value to be mutable or a non-readonly byref type. - byref 확장 메서드 '{0}'을(를) 호출할 수 없습니다. 첫 번째 매개 변수는 변경할 수 있거나 읽기 전용이 아닌 byref 형식인 값이 필요합니다. + byref 확장 메서드 '{0}'을(를) 호출할 수 없습니다. ‘이’ 매개 변수는 변경할 수 있거나 읽기 전용이 아닌 byref 형식인 값이 필요합니다. @@ -8634,7 +8649,7 @@ Package manager key '{0}' was not registered in {1}. Currently registered: {2}. You can provide extra path(s) by passing '--compilertool:<extensionsfolder>' to the command line. To learn more about extensions, visit: https://aka.ms/dotnetdepmanager - 패키지 관리자 키 '{0}'이(가) {1}에서 등록되지 않았습니다. 현재 등록: {2}. 확장에 대한 자세한 내용은 다음을 참조하세요. https://aka.ms/dotnetdepmanager + 패키지 관리자 키 '{0}'이(가) {1}에 등록되지 않았습니다. 현재 등록됨: {2}. 명령줄에 '--compilertool:<extensionsfolder>'를 전달하여 추가 경로를 제공할 수 있습니다. 확장에 대한 자세한 내용은 다음을 참조하세요. https://aka.ms/dotnetdepmanager diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index c3e44915a0c..100ba5dfc89 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -84,7 +84,7 @@ An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. - An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. + Metoda pobierająca i metoda ustawiająca właściwości indeksowanej muszą mieć taki sam typ. Właściwość „{0}” ma metodę pobierającą typu „{1}”, ale metodę ustawiającą typu „{2}”. @@ -124,12 +124,12 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. - Object expressions cannot implement interfaces with static abstract members or declare static members. + Wyrażenia obiektów nie mogą implementować interfejsów ze statycznymi abstrakcyjnymi elementami członkowskimi ani deklarować statycznych elementów członkowskich. The TailCall attribute should only be applied to recursive functions. - The TailCall attribute should only be applied to recursive functions. + Atrybut TailCall powinien być stosowany tylko do funkcji rekursywnych. @@ -147,6 +147,11 @@ Dostępne przeciążenia:\n{0} + + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + Element „{0}” nie obsługuje typu „{1}”, ponieważ ten drugi nie ma wymaganej (rzeczywistej lub wbudowanej) składowej „{2}” + + 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. @@ -274,7 +279,7 @@ Raises warnings if the 'TailCall' attribute is used on non-recursive functions. - Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Zgłasza ostrzeżenia, jeśli atrybut „TailCall” jest używany w funkcjach niekursywnych. @@ -444,7 +449,7 @@ prefer extension method over plain property - prefer extension method over plain property + preferuj metodę rozszerzenia nad zwykłą właściwością @@ -489,7 +494,7 @@ Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type - Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type + Udostępnij pola źródłowe w unii rozłącznej [<Struct>], o ile mają taką samą nazwę i ten sam typ @@ -529,7 +534,7 @@ Union case test properties - Union case test properties + Właściwości testowe przypadku unii @@ -544,7 +549,7 @@ Indexed properties getter and setter must have the same type - Indexed properties getter and setter must have the same type + Metoda pobierająca i metoda ustawiająca właściwości indeksowanych muszą mieć taki sam typ. @@ -944,7 +949,7 @@ Expecting record field - Expecting record field + Oczekiwanie pola rekordu @@ -987,9 +992,14 @@ Dostęp tego elementu członkowskiego jest niejednoznaczny. W celu utworzenia obiektu użyj nawiasów, na przykład „(nowy SomeType(args)).MemberName” + + Only simple patterns are allowed in primary constructors + Only simple patterns are allowed in primary constructors + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. - Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. + Niekompletna deklaracja konstrukcji statycznej. Użyj elementu „static let”, „static do”, „static member” lub „static val” na potrzeby deklaracji. @@ -1189,7 +1199,7 @@ Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. - Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. + Składnia lambda skrótu jest obsługiwana tylko w przypadku wyrażeń niepodzielnych, takich jak metoda, właściwość, pole lub indeksator w dorozumianym argumencie „_”. Na przykład: „let f = _. Length”. @@ -1229,7 +1239,7 @@ This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. - This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. + To jest definicja funkcji, która zasłania przypadek unii. Jeśli to jest to, czego chcesz, zignoruj lub pomiń to ostrzeżenie. Jeśli chcesz, aby była to dekonstrukcja przypadku unii, dodaj nawiasy. @@ -1329,12 +1339,12 @@ No static abstract member was found that corresponds to this override - No static abstract member was found that corresponds to this override + Nie odnaleziono żadnego statycznego abstrakcyjnego elementu członkowskiego odpowiadającego temu przesłonięciu No static abstract property was found that corresponds to this override - No static abstract property was found that corresponds to this override + Nie odnaleziono żadnej statycznej właściwości abstrakcyjnej odpowiadającej temu przesłonięciu @@ -1434,7 +1444,7 @@ If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. - If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. + Jeśli typ unii wieloskładnikowej jest strukturą, wszystkie pola o tej samej nazwie muszą być tego samego typu. Ta reguła ma zastosowanie również do wygenerowanej nazwy „item” w przypadku pól bez nazwy. @@ -1497,6 +1507,11 @@ Deklarowanie \"interfejsów ze statycznymi metodami abstrakcyjnymi\" jest funkcją zaawansowaną. Aby uzyskać wskazówki, zobacz https://aka.ms/fsharp-iwsams. To ostrzeżenie można wyłączyć przy użyciu polecenia „#nowarn \"3535\"" lub "--nowarn:3535”. + + The type '{0}' has too many methods. Found: '{1}', maximum: '{2}' + Typ „{0}” ma zbyt wiele metod. Znaleziono: „{1}”, maksimum: „{2}” + + Interface member '{0}' does not have a most specific implementation. Składowa interfejsu „{0}” nie ma najbardziej specyficznej implementacji. @@ -1659,7 +1674,7 @@ Parentheses can be removed. - Parentheses can be removed. + Nawiasy można usunąć. @@ -5139,7 +5154,7 @@ For F#7 and lower, static 'let','do' and 'member val' definitions may only be used in types with a primary constructor ('type X(args) = ...'). To enable them in all other types, use language version '8' or higher. - W przypadku języka F#7 i niższych, definicje wartości statycznych mogą być używane tylko w typach z konstruktorem podstawowym („type X(args) = ...”). Aby włączyć je we wszystkich innych typach, użyj wersji językowej „wersja zapoznawcza”. + W przypadku języka F#7 i niższych wersji, definicje statyczne „let”,„do” i „member val” mogą być używane tylko w typach z konstruktorem podstawowym („type X(args) = ...”). Aby włączyć je we wszystkich innych typach, użyj wersji „8” języka lub wyższej. @@ -8544,7 +8559,7 @@ Cannot call the byref extension method '{0}. 'this' parameter requires the value to be mutable or a non-readonly byref type. - Nie można wywołać metody rozszerzenia byref „{0}”. Pierwszy parametr wymaga, aby wartość była typem byref zmiennym lub innym niż tylko do odczytu. + Nie można wywołać metody rozszerzenia byref „{0}”. parametr „this” wymaga, aby wartość była typem byref podlegającym zmianie lub innym niż tylko do odczytu. @@ -8634,7 +8649,7 @@ Package manager key '{0}' was not registered in {1}. Currently registered: {2}. You can provide extra path(s) by passing '--compilertool:<extensionsfolder>' to the command line. To learn more about extensions, visit: https://aka.ms/dotnetdepmanager - Klucz menedżera pakietów „{0}” nie został zarejestrowany w {1}. Aktualnie zarejestrowane: {2}. Aby dowiedzieć się więcej o rozszerzeniach, odwiedź stronę: https://aka.ms/dotnetdepmanager + Klucz menedżera pakietów „{0}” nie został zarejestrowany w {1}. Aktualnie zarejestrowane: {2}. Możesz podać dodatkowe ścieżki, przekazując polecenie „--compilertool:<extensionsfolder>” do wiersza polecenia. Aby dowiedzieć się więcej o rozszerzeniach, odwiedź stronę: https://aka.ms/dotnetdepmanager diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index fd797b5beec..9e3e0f68919 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -84,7 +84,7 @@ An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. - An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. + O getter e o setter de uma propriedade devem ter o mesmo tipo. A propriedade "{0}" possui getter do tipo "{1}", mas setter do tipo "{2}". @@ -124,12 +124,12 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. - Object expressions cannot implement interfaces with static abstract members or declare static members. + Expressões de objeto não podem implementar interfaces com membros abstratos estáticos ou declarar membros estáticos. The TailCall attribute should only be applied to recursive functions. - The TailCall attribute should only be applied to recursive functions. + O atributo TailCall só deve ser aplicado a funções recursivas. @@ -147,6 +147,11 @@ Sobrecargas disponíveis:\n{0} + + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + "{0}" não dá suporte ao tipo "{1}", pois o último não tem o membro necessário (real ou interno) "{2}: + + 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. @@ -274,7 +279,7 @@ Raises warnings if the 'TailCall' attribute is used on non-recursive functions. - Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Gera avisos se o atributo "TailCall" for usado em funções não recursivas. @@ -444,7 +449,7 @@ prefer extension method over plain property - prefer extension method over plain property + preferir o método de extensão em vez da propriedade simples @@ -489,7 +494,7 @@ Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type - Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type + Compartilhar campos subjacentes em uma união discriminada [<Struct>], desde que tenham o mesmo nome e tipo @@ -529,7 +534,7 @@ Union case test properties - Union case test properties + Propriedades de teste de caso de união @@ -544,7 +549,7 @@ Indexed properties getter and setter must have the same type - Indexed properties getter and setter must have the same type + As propriedades indexadas getter e setter devem ter o mesmo tipo @@ -944,7 +949,7 @@ Expecting record field - Expecting record field + Esperando campo de registro @@ -987,9 +992,14 @@ Este acesso de membro é ambíguo. Use parênteses em torno da criação do objeto, por exemplo, '(new SomeType(args)).MemberName''. + + Only simple patterns are allowed in primary constructors + Only simple patterns are allowed in primary constructors + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. - Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. + Declaração incompleta de um constructo estático. Use "static let","static do","static member" ou "static val" para declaração. @@ -1189,7 +1199,7 @@ Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. - Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. + A sintaxe lambda abreviada só tem suporte para expressões atômicas, como método, propriedade, campo ou indexador no argumento '_' implícito. Por exemplo: 'let f = _. Comprimento'. @@ -1229,7 +1239,7 @@ This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. - This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. + Essa é uma definição de função que sombra um caso de união. Se isso for o que você deseja, ignore ou suprime este aviso. Se você quiser que ele seja uma desconstrução de caso de união, adicione parênteses. @@ -1329,12 +1339,12 @@ No static abstract member was found that corresponds to this override - No static abstract member was found that corresponds to this override + Nenhum membro abstrato estático encontrado que corresponda a esta substituição No static abstract property was found that corresponds to this override - No static abstract property was found that corresponds to this override + Nenhuma propriedade abstrata que corresponde a esta substituição foi encontrada @@ -1434,7 +1444,7 @@ If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. - If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. + Se um tipo de união multicase for um struct, todos os campos com o mesmo nome deverão ser do mesmo tipo. Essa regra também se aplica ao nome 'Item' gerado no caso de campos sem nome. @@ -1497,6 +1507,11 @@ Declarando \"interfaces com métodos abstratos estáticos\" é um recurso avançado. Consulte https://aka.ms/fsharp-iwsams para obter diretrizes. Você pode desabilitar esse aviso usando '#nowarn \"3535\"' ou '--nowarn:3535'. + + The type '{0}' has too many methods. Found: '{1}', maximum: '{2}' + O tipo "{0}" tem muitos métodos. Encontrado: "{1}", máximo: "{2}" + + Interface member '{0}' does not have a most specific implementation. O membro de interface '{0}' não tem uma implementação mais específica. @@ -1659,7 +1674,7 @@ Parentheses can be removed. - Parentheses can be removed. + Os parênteses podem ser removidos. @@ -5139,7 +5154,7 @@ For F#7 and lower, static 'let','do' and 'member val' definitions may only be used in types with a primary constructor ('type X(args) = ...'). To enable them in all other types, use language version '8' or higher. - Para F#7 e inferior, as definições de valores estáticos só podem ser usadas em tipos com um construtor primário ('type X(args) = ...'). Para habilitá-los em todos os outros tipos, use a versão do idioma “versão prévia”. + Para F#7 e inferior, as definições de valores estáticos só podem ser usadas em tipos com um construtor primário ('type X(args) = ...'). Para habilitá-los em todos os outros tipos, use a versão do idioma “versão prévia”. @@ -8544,7 +8559,7 @@ Cannot call the byref extension method '{0}. 'this' parameter requires the value to be mutable or a non-readonly byref type. - Não é possível chamar o método de extensão de byref '{0}. O primeiro parâmetro requer que o valor seja mutável ou não seja byref somente leitura. + Não é possível chamar o método de extensão de byref '{0}. O primeiro parâmetro requer que o valor seja mutável ou não seja byref somente leitura. @@ -8634,7 +8649,7 @@ Package manager key '{0}' was not registered in {1}. Currently registered: {2}. You can provide extra path(s) by passing '--compilertool:<extensionsfolder>' to the command line. To learn more about extensions, visit: https://aka.ms/dotnetdepmanager - A chave do gerenciador de pacotes “{0}” não foi registrada em {1}. Atualmente cadastrado: {2}. Para saber mais sobre extensões, visite: https://aka.ms/dotnetdepmanager + A chave do gerenciador de pacotes “{0}” não foi registrada em {1}. Atualmente cadastrado: {2}. Você pode fornecer caminhos extras passando "--compilertool:<extensionsfolder>" para a linha de comando. Para saber mais sobre extensões, visite: https://aka.ms/dotnetdepmanager diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 8b1cad66105..bb1641fcdee 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -84,7 +84,7 @@ An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. - An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. + Методы получения и установки индексированного свойства должны иметь один и тот же тип. Свойство "{0}" имеет метод получения типа "{1}" и метод задания типа "{2}". @@ -124,12 +124,12 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. - Object expressions cannot implement interfaces with static abstract members or declare static members. + Выражения объектов не могут реализовывать интерфейсы со статическими абстрактными членами или объявлять статические члены. The TailCall attribute should only be applied to recursive functions. - The TailCall attribute should only be applied to recursive functions. + Атрибут TailCall следует применять только к рекурсивным функциям. @@ -147,6 +147,11 @@ Доступные перегрузки:\n{0} + + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' не поддерживает тип '{1}', поскольку у последнего отсутствует необходимый (реальный или встроенный) член '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. В универсальной конструкции требуется использовать параметр универсального типа, известный как структура или ссылочный тип. Рекомендуется добавить заметку с типом. @@ -274,7 +279,7 @@ Raises warnings if the 'TailCall' attribute is used on non-recursive functions. - Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Выдает предупреждения, если атрибут TailCall используется в нерекурсивных функциях. @@ -444,7 +449,7 @@ prefer extension method over plain property - prefer extension method over plain property + предпочитать метод расширения вместо простого свойства @@ -489,7 +494,7 @@ Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type - Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type + Совместное использование базовых полей в дискриминируемом объединении [<Struct>], если они имеют одинаковое имя и тип. @@ -529,7 +534,7 @@ Union case test properties - Union case test properties + Свойства теста союзного случая @@ -544,7 +549,7 @@ Indexed properties getter and setter must have the same type - Indexed properties getter and setter must have the same type + Методы получения и установки индексированных свойств должны иметь один и тот же тип. @@ -944,7 +949,7 @@ Expecting record field - Expecting record field + Ожидается поле записи @@ -987,9 +992,14 @@ Неоднозначный доступ к этому элементу. Заключите операцию создания объекта в круглые скобки, например (new Объект(аргументы)).Элемент + + Only simple patterns are allowed in primary constructors + Only simple patterns are allowed in primary constructors + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. - Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. + Неполное объявление статической конструкции. Для объявления используйте «static let», «static do», «staticmember» или «static val». @@ -1189,7 +1199,7 @@ Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. - Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. + Сокращенный синтаксис лямбда-выражений поддерживается только для атомарных выражений, таких как метод, свойство, поле или индексатор подразумеваемого аргумента «_». Например: 'let f = _.Length'. @@ -1229,7 +1239,7 @@ This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. - This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. + Это определение функции, которое отражает случай объединения. Если это то, что вы хотите, игнорируйте или подавляйте это предупреждение. Если вы хотите, чтобы это была деконструкция регистра объединения, добавьте круглые скобки. @@ -1329,12 +1339,12 @@ No static abstract member was found that corresponds to this override - No static abstract member was found that corresponds to this override + Не найден статический абстрактный элемент, соответствующий этому переопределению. No static abstract property was found that corresponds to this override - No static abstract property was found that corresponds to this override + Не найдено статическое абстрактное свойство, соответствующее этому переопределению. @@ -1434,7 +1444,7 @@ If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. - If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. + Если тип объединения нескольких регистров является структурой, то все поля с одинаковым именем должны быть одного типа. Это правило также применяется к сгенерированному имени «Элемент» в случае безымянных полей. @@ -1497,6 +1507,11 @@ Объявление \"интерфейсов со статическими абстрактными методами\" является расширенной функцией. См. руководство на https://aka.ms/fsharp-iwsams. Это предупреждение можно отключить с помощью используя "#nowarn \"3535\"" or "--nowarn:3535". + + The type '{0}' has too many methods. Found: '{1}', maximum: '{2}' + Тип '{0}' имеет слишком много методов. Найдено: '{1}', максимально: '{2}' + + Interface member '{0}' does not have a most specific implementation. Элемент интерфейса "{0}" не имеет наиболее конкретной реализации. @@ -1659,7 +1674,7 @@ Parentheses can be removed. - Parentheses can be removed. + Круглые скобки можно убрать. @@ -5139,7 +5154,7 @@ For F#7 and lower, static 'let','do' and 'member val' definitions may only be used in types with a primary constructor ('type X(args) = ...'). To enable them in all other types, use language version '8' or higher. - Определения статических значений для F#7 и ниже можно использовать только в типах с первичным конструктором ("type X(args) = ..."). Чтобы включить их во всех других типах, используйте версию языка "preview". + Определения статических значений "let","do" и "member val" для F#7 и ниже можно использовать только в типах с первичным конструктором ("type X(args) = ..."). Чтобы включить их во всех других типах, используйте версию языка "8" или выше. @@ -8544,7 +8559,7 @@ Cannot call the byref extension method '{0}. 'this' parameter requires the value to be mutable or a non-readonly byref type. - Не удается вызвать метод расширения byref "{0}". В качестве первого параметра необходимо указать изменяемое значение или значение типа byref, доступное не только для чтения. + Не удается вызвать метод расширения byref "{0}". В качестве параметра "this" необходимо указать изменяемое значение или значение типа byref, доступное не только для чтения. @@ -8634,7 +8649,7 @@ Package manager key '{0}' was not registered in {1}. Currently registered: {2}. You can provide extra path(s) by passing '--compilertool:<extensionsfolder>' to the command line. To learn more about extensions, visit: https://aka.ms/dotnetdepmanager - Ключ диспетчера пакетов "{0}" не зарегистрирован в {1}. Сейчас зарегистрировано: {2}. Дополнительные сведения о расширениях см. на странице https://aka.ms/dotnetdepmanager + Ключ диспетчера пакетов "{0}" не зарегистрирован в {1}. Сейчас зарегистрировано: {2}. Чтобы указать дополнительные пути, передайте в командную строку "--compilertool:<extensionsfolder>". Дополнительные сведения о расширениях см. на странице https://aka.ms/dotnetdepmanager diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 84434185a19..9c753835425 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -84,7 +84,7 @@ An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. - An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. + Dizini oluşturulmuş bir özelliğin alıcısı ve ayarlayıcısı aynı türde olmalıdır. '{0}' özelliği '{1}' türünde alıcıya ancak '{2}' türünde ayarlayıcıya sahip. @@ -124,12 +124,12 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. - Object expressions cannot implement interfaces with static abstract members or declare static members. + Nesne ifadeleri, statik soyut üyeler içeren arabirimleri uygulayamaz veya statik üyeleri bildiremez. The TailCall attribute should only be applied to recursive functions. - The TailCall attribute should only be applied to recursive functions. + TailCall özniteliği yalnızca özyinelemeli işlevlere uygulanmalıdır. @@ -147,6 +147,11 @@ Kullanılabilir aşırı yüklemeler:\n{0} + + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}', gerekli (gerçek veya yerleşik) '{2}' üyesine sahip olmadığından '{1}' türünü desteklemiyor + + 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. @@ -274,7 +279,7 @@ Raises warnings if the 'TailCall' attribute is used on non-recursive functions. - Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + 'TailCall' özniteliği özyinelemeli olmayan işlevlerde kullanılıyorsa uyarılar oluşturur. @@ -444,7 +449,7 @@ prefer extension method over plain property - prefer extension method over plain property + Basit özellik yerine genişletme yöntemini tercih edin @@ -489,7 +494,7 @@ Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type - Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type + Aynı ada ve türe sahip oldukları sürece temel alınan alanları [<Struct>] ayırt edici birleşim biçiminde paylaşın @@ -529,7 +534,7 @@ Union case test properties - Union case test properties + Birleşim durumu test özellikleri @@ -544,7 +549,7 @@ Indexed properties getter and setter must have the same type - Indexed properties getter and setter must have the same type + Dizini oluşturulmuş özelliklerin alıcısı ve ayarlayıcısı aynı türde olmalıdır @@ -944,7 +949,7 @@ Expecting record field - Expecting record field + Kayıt alanı bekleniyor @@ -987,9 +992,14 @@ Bu üye erişimi belirsiz. Lütfen nesne oluşturma etrafında parantez kullanın, örneğin '(yeni SomeType (args)).MemberName’ + + Only simple patterns are allowed in primary constructors + Only simple patterns are allowed in primary constructors + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. - Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. + Statik yapının bildirimi eksik. Bildirim için 'static let','static do','static member' veya 'static val' kullanın. @@ -1189,7 +1199,7 @@ Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. - Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. + Toplu lambda söz dizimi yalnızca örtülü '_' bağımsız değişkeninde yöntem, özellik, alan veya dizin oluşturucu gibi atomik ifadeler için destekleniyor. Örnek: 'let f = _.Length'. @@ -1229,7 +1239,7 @@ This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. - This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. + Bu, bir birleşim durumunu gizleyen bir işlev tanımıdır. Bunu istiyorsanız, bu uyarıyı yoksayın veya durdurun. Bunun bir birleşim durumu ayrıştırması olmasını istiyorsanız, parantezler ekleyin. @@ -1329,12 +1339,12 @@ No static abstract member was found that corresponds to this override - No static abstract member was found that corresponds to this override + Bu geçersiz kılmaya karşılık gelen hiçbir statik soyut üye bulunamadı No static abstract property was found that corresponds to this override - No static abstract property was found that corresponds to this override + Bu geçersiz kılmaya karşılık gelen hiçbir statik soyut özellik bulunamadı @@ -1434,7 +1444,7 @@ If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. - If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. + Çok durumlu bir birleşim türü bir yapıysa, aynı ada sahip tüm alanların aynı türde olması gerekir. Bu kural adlandırılmamış alanlar olması durumunda oluşturulan ‘Öğe’ adı için de geçerlidir. @@ -1497,6 +1507,11 @@ \"interfaces with static abstract methods\" bildirimi gelişmiş bir özelliktir. Rehber için bkz. https://aka.ms/fsharp-iwsams. '#nowarn \"3535\"' veya '--nowarn:3535'. kullanarak bu uyarıyı devre dışı bırakabilirsiniz. + + The type '{0}' has too many methods. Found: '{1}', maximum: '{2}' + '{0}' türü çok fazla yöntem içeriyor. Bulunan: '{1}', üst sınır: '{2}' + + Interface member '{0}' does not have a most specific implementation. '{0}' arabirim üyesinin en belirgin uygulaması yok. @@ -1659,7 +1674,7 @@ Parentheses can be removed. - Parentheses can be removed. + Parantezler kaldırılamaz. @@ -5139,7 +5154,7 @@ For F#7 and lower, static 'let','do' and 'member val' definitions may only be used in types with a primary constructor ('type X(args) = ...'). To enable them in all other types, use language version '8' or higher. - F#7 ve altı için, statik değer tanımları yalnızca birincil oluşturucu ('type X(args) = ...') içeren türlerde kullanılabilir. Bunları diğer tüm türlerde etkinleştirmek için 'önizleme' dil sürümünü kullanın. + F#7 ve altı için, 'let', 'do' ve 'member val' statik değer tanımları yalnızca birincil oluşturucu ('type X(args) = ...') içeren türlerde kullanılabilir. Bunları diğer tüm türlerde etkinleştirmek için dil sürümü '8' ve üstünü kullanın. @@ -8544,7 +8559,7 @@ Cannot call the byref extension method '{0}. 'this' parameter requires the value to be mutable or a non-readonly byref type. - '{0}' byref genişletme metodu çağrılamıyor. İlk parametre, değerin değişebilir olmasını veya salt okunur olmayan bir byref türünde olmasını gerektiriyor. + '{0}' byref genişletme metodu çağrılamıyor. ‘this’ parametresi, değerin değişebilir olmasını veya salt okunur olmayan bir byref türünde olmasını gerektiriyor. @@ -8634,7 +8649,7 @@ Package manager key '{0}' was not registered in {1}. Currently registered: {2}. You can provide extra path(s) by passing '--compilertool:<extensionsfolder>' to the command line. To learn more about extensions, visit: https://aka.ms/dotnetdepmanager - Paket yöneticisi '{0}' anahtar anahtarı bu makinede {1}. Şu anda kayıtlı: {2}. Uzantılar hakkında daha fazla bilgi edinmek için şu adresi ziyaret edin: https://aka.ms/dotnetdepmanager + Paket yöneticisi anahtarı '{0}' {1} altında kayıtlı değil. Şu anda kayıtlı: {2}. Komut satırına '--compilertool:<extensionsfolder>' geçirerek ek yollar sağlayabilirsiniz. Uzantılar hakkında daha fazla bilgi edinmek için şu adresi ziyaret edin: https://aka.ms/dotnetdepmanager diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 979456fe365..ee6832b2fa4 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -84,7 +84,7 @@ An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. - An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. + 索引属性的 Getter 和 Setter 的类型必须相同。属性“{0}”的 Getter 的类型为“{1}”,而 Setter 的类型为“{2}”。 @@ -124,12 +124,12 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. - Object expressions cannot implement interfaces with static abstract members or declare static members. + 对象表达式无法实现具有静态抽象成员或声明静态成员的接口。 The TailCall attribute should only be applied to recursive functions. - The TailCall attribute should only be applied to recursive functions. + TailCall 属性应仅应用于递归函数。 @@ -147,6 +147,11 @@ 可用重载:\n{0} + + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + “{0}”不支持类型“{1}”,因为后者缺少所需的(实际或内置)成员“{2}” + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. 泛型构造要求泛型类型参数被视为结构或引用类型。请考虑添加类型注释。 @@ -274,7 +279,7 @@ Raises warnings if the 'TailCall' attribute is used on non-recursive functions. - Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + 如果在非递归函数上使用“TailCall”属性,则引发警告。 @@ -444,7 +449,7 @@ prefer extension method over plain property - prefer extension method over plain property + 首选扩展方法而不是纯属性 @@ -489,7 +494,7 @@ Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type - Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type + 只要它们具有相同的名称和类型,即可在 [<Struct>] 中共享基础字段 @@ -529,7 +534,7 @@ Union case test properties - Union case test properties + 联合用例测试属性 @@ -544,7 +549,7 @@ Indexed properties getter and setter must have the same type - Indexed properties getter and setter must have the same type + 索引属性 getter 和 setter 必须具有相同的类型 @@ -944,7 +949,7 @@ Expecting record field - Expecting record field + 应为记录字段 @@ -987,9 +992,14 @@ 此成员访问权限不明确。请在对象创建周围使用括号,例如 “(new SomeType(args)).MemberName” + + Only simple patterns are allowed in primary constructors + Only simple patterns are allowed in primary constructors + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. - Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. + 静态构造的声明不完整。使用“static let”、“static do”、“static member”或“static val”进行声明。 @@ -1189,7 +1199,7 @@ Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. - Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. + 仅原子表达式支持速记 lambda 语法,例如隐含的“_”参数上的方法、属性、字段或索引器。例如:“let f = _.Length”。 @@ -1229,7 +1239,7 @@ This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. - This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. + 这是一个隐藏联合事例的函数定义。如果这是你想要的,请忽略或取消此警告。如果希望它是联合大小写析构,请添加括号。 @@ -1329,12 +1339,12 @@ No static abstract member was found that corresponds to this override - No static abstract member was found that corresponds to this override + 找不到与此替代对应的静态抽象成员 No static abstract property was found that corresponds to this override - No static abstract property was found that corresponds to this override + 未找到与此重写对应的静态抽象属性 @@ -1434,7 +1444,7 @@ If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. - If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. + 如果多重联合类型是结构,则具有相同名称的所有字段必须具有相同的类型。对于未命名字段,此规则也适用于生成的“Item”名称。 @@ -1497,6 +1507,11 @@ 声明“使用静态抽象方法的接口”是一项高级功能。有关指南,请参阅 https://aka.ms/fsharp-iwsams。可以使用 "#nowarn \"3535\"' 或 '--nowarn:3535' 禁用此警告。 + + The type '{0}' has too many methods. Found: '{1}', maximum: '{2}' + 类型“{0}”的方法太多。1️⃣找到:“{1}”,最大值:“{2}” + + Interface member '{0}' does not have a most specific implementation. 接口成员“{0}”没有最具体的实现。 @@ -1659,7 +1674,7 @@ Parentheses can be removed. - Parentheses can be removed. + 可以移除括号。 @@ -5139,7 +5154,7 @@ For F#7 and lower, static 'let','do' and 'member val' definitions may only be used in types with a primary constructor ('type X(args) = ...'). To enable them in all other types, use language version '8' or higher. - 对于 F#7 及更低版本,静态值定义只能用于具有主构造函数的类型 ("type X(args) = ...")。若要在所有其他类型中启用它们,请使用“预览版”语言版本。 + 对于 F#7 及更低版本,静态“let”、“do”和“member val”定义只能用于具有主构造函数的类型 ("type X(args) = ...")。若要在所有其他类型中启用它们,请使用语言版本“8”或更高版本。 @@ -8544,7 +8559,7 @@ Cannot call the byref extension method '{0}. 'this' parameter requires the value to be mutable or a non-readonly byref type. - 无法调用 byref 扩展方法 "{0}"。第一个参数要求该值是可变的或非只读的 byref 类型。 + 无法调用 byref 扩展方法 "{0}"。“'this”参数要求该值是可变的或非只读的 byref 类型。 @@ -8634,7 +8649,7 @@ Package manager key '{0}' was not registered in {1}. Currently registered: {2}. You can provide extra path(s) by passing '--compilertool:<extensionsfolder>' to the command line. To learn more about extensions, visit: https://aka.ms/dotnetdepmanager - {0} 中未注册包管理器密钥“{1}”。当前已注册: {2}。若要详细了解扩展,请访问: https://aka.ms/dotnetdepmanager + 未在 {1} 中注册包管理器密钥“{0}”。当前已注册: {2}。可以通过将“--compilertool:<extensionsfolder>”传递到命令行来提供额外的路径。若要了解有关扩展的详细信息,请访问: https://aka.ms/dotnetdepmanager diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 8d4fef2991f..125697b5871 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -84,7 +84,7 @@ An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. - An indexed property's getter and setter must have the same type. Property '{0}' has getter of type '{1}' but setter of type '{2}'. + 索引屬性的 getter 和 setter 必須具有相同類型。屬性 '{0}' 的 getter 類型為 '{1}',但 setter 類型為 '{2}'。 @@ -124,12 +124,12 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. - Object expressions cannot implement interfaces with static abstract members or declare static members. + 物件運算式無法實作具有靜態抽象成員的介面或宣告靜態成員。 The TailCall attribute should only be applied to recursive functions. - The TailCall attribute should only be applied to recursive functions. + TailCall 屬性只應套用至遞迴函數。 @@ -147,6 +147,11 @@ 可用的多載:\n{0} + + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' 不支援類型 '{1}',因為後者缺少必要的 (實際或內建) 成員 '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. 泛型建構要求泛型型別參數必須指定為結構或參考型別。請考慮新增型別註解。 @@ -274,7 +279,7 @@ Raises warnings if the 'TailCall' attribute is used on non-recursive functions. - Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + 如果 'TailCall' 屬性用於非遞迴函數,則引發警告。 @@ -444,7 +449,7 @@ prefer extension method over plain property - prefer extension method over plain property + 偏好延伸模組方法勝於純文字屬性 @@ -489,7 +494,7 @@ Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type - Share underlying fields in a [<Struct>] discriminated union as long as they have same name and type + 只要 [<Struct>] 具有相同名稱和類型,就以強制聯集共用基礎欄位 @@ -529,7 +534,7 @@ Union case test properties - Union case test properties + 聯集案例測試屬性 @@ -544,7 +549,7 @@ Indexed properties getter and setter must have the same type - Indexed properties getter and setter must have the same type + 索引屬性 getter 和 setter 必須具有相同的類型 @@ -944,7 +949,7 @@ Expecting record field - Expecting record field + 必須是記錄欄位 @@ -987,9 +992,14 @@ 此成員存取不明確。請在物件建立前後加上括弧,例如「(new SomeType(args)).MemberName」 + + Only simple patterns are allowed in primary constructors + Only simple patterns are allowed in primary constructors + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. - Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. + 不完整的靜態建構宣告。使用 'static let'、'static do'、'static member' 或 'static val' 進行宣告。 @@ -1189,7 +1199,7 @@ Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. - Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. + 只有不可部分完成運算式才支援速記 Lambda 語法,例如隱含 '_' 引數上的方法、屬性、欄位或索引子。例如: 'let f = _.Length'。 @@ -1229,7 +1239,7 @@ This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. - This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses. + 這是陰影等位案例的函式定義。如果這是您要的,請忽略或隱藏此警告。如果您希望它是等位案例解構,請新增括弧。 @@ -1329,12 +1339,12 @@ No static abstract member was found that corresponds to this override - No static abstract member was found that corresponds to this override + 找不到對應到這個覆寫的靜態抽象成員 No static abstract property was found that corresponds to this override - No static abstract property was found that corresponds to this override + 找不到對應到這個覆寫的靜態抽象屬性 @@ -1434,7 +1444,7 @@ If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. - If a multicase union type is a struct, then all fields with the same name must be of the same type. This rule applies also to the generated 'Item' name in case of unnamed fields. + 如果多寫聯集類型是結構,則所有具有相同名稱的欄位都必須是相同的類型。此規則也適用於未命名欄位時產生的 'Item' 名稱。 @@ -1497,6 +1507,11 @@ 使用「靜態抽象方法宣告介面」是進階的功能。請參閱 https://aka.ms/fsharp-iwsams 以尋求指引。您可以使用 '#nowarn \"3535\"' 或 '--nowarn:3535' 來停用此警告。 + + The type '{0}' has too many methods. Found: '{1}', maximum: '{2}' + 類型 '{0}' 有太多方法。找到: '{1}',最大值: '{2}' + + Interface member '{0}' does not have a most specific implementation. 介面成員 '{0}' 沒有最具體的實作。 @@ -1659,7 +1674,7 @@ Parentheses can be removed. - Parentheses can be removed. + 可以移除括號。 @@ -5139,7 +5154,7 @@ For F#7 and lower, static 'let','do' and 'member val' definitions may only be used in types with a primary constructor ('type X(args) = ...'). To enable them in all other types, use language version '8' or higher. - 對於 F#7 和更低版本,靜態值定義只能用於具有主要建構函式的類型 ('type X(args) = ...')。若要在所有其他類型中啟用,請使用語言版本 'preview'。 + 對於 F#7 和更低版本,靜態 'let'、'do' 和 'member val' 定義只能用於具有主要建構函式的類型 ('type X(args) = ...')。若要在所有其他類型中啟用,請使用語言版本 '8' 或更新版本。 @@ -8544,7 +8559,7 @@ Cannot call the byref extension method '{0}. 'this' parameter requires the value to be mutable or a non-readonly byref type. - 無法呼叫 byref 擴充方法 '{0}。第一個參數需要值可變動,或為非唯讀 byref 類型。 + 無法呼叫 byref 擴充方法 '{0}。'this' 參數需要值可變動,或為非唯讀 byref 類型。 @@ -8634,7 +8649,7 @@ Package manager key '{0}' was not registered in {1}. Currently registered: {2}. You can provide extra path(s) by passing '--compilertool:<extensionsfolder>' to the command line. To learn more about extensions, visit: https://aka.ms/dotnetdepmanager - 未在 {1} 中註冊套件管理員金鑰 '{0}'。目前已註冊: {2}。若要深入了解延伸模組,請瀏覽: https://aka.ms/dotnetdepmanager + 未在 {1} 中登錄封裝管理員金鑰 '{0}'。目前註冊: {2}。您可以將 '--compilertool:<extensionsfolder>' 傳遞至命令列,以提供額外路徑。如需深入了解延伸模組,請瀏覽: https://aka.ms/dotnetdepmanager diff --git a/src/Compiler/xlf/FSStrings.cs.xlf b/src/Compiler/xlf/FSStrings.cs.xlf index b2a4e04e6c4..16a05e5a27a 100644 --- a/src/Compiler/xlf/FSStrings.cs.xlf +++ b/src/Compiler/xlf/FSStrings.cs.xlf @@ -44,12 +44,12 @@ Non-static member is expected. - Non-static member is expected. + Očekává se nestatický člen. Static member is expected. - Static member is expected. + Očekává se statický člen. @@ -227,6 +227,16 @@ Pole {0} a {1} jsou odlišného typu. + + Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x<'a>".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Omezení hodnoty: Hodnota {0} má odvozený obecný typ\n {1}\nNicméně hodnoty nemohou mít proměnné obecného typu jako '_a v "let x: '_a". Můžete provést jednu z následujících akcí:\n- Definujte jej jako jednoduchý datový termín, například celočíselný literál, řetězcový literál nebo případ sjednocení, například let x = 1\n- Přidejte explicitní typovou anotaci, například let x : int\n- Použijte hodnotu jako negenerický typ v pozdějším kódu pro typovou inferenci, jako například do x\nebo pokud přesto chcete typové výsledky, můžete místo toho {2} definovat jako funkci, a to buď:\n- Přidejte jednotkový parametr, jako například let x()\n- Napište explicitní typové parametry, jako například let x<'a>.\nTato chyba je způsobena tím, že vazba let bez parametrů definuje hodnotu, nikoli funkci. Hodnoty nemůžou být generické, protože se předpokládá, že výsledkem čtení hodnoty bude všude totéž, ale generické typové parametry mohou tento předpoklad zrušit tím, že umožní získat výsledky závislé na typu. + + + + Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f<'a>"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -> obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Omezení hodnoty: Hodnota {0} má odvozený obecný typ funkce.\n {1}\n Hodnoty ale nemůžou mít proměnné obecného typu, například _a v let f: _a. Místo toho byste měli {2} definovat jako funkci některým z následujících postupů:\n- Přidejte explicitní parametr, který se použije místo částečné aplikace let f param\n- Přidejte jednotkový parametr jako let f()\n- Napište explicitní typové parametry jako let f<'a>\nebo pokud nemáte v úmyslu, aby byl generický:\n- Přidejte explicitní typovou anotaci jako let f : obj -> obj\n- Použijte argumenty negenerických typů na hodnotu funkce v pozdějším kódu pro typovou inferenci jako do f().\nTato chyba je způsobena tím, že vazba let bez parametrů definuje hodnotu, nikoli funkci. Hodnoty nemůžou být generické, protože se předpokládá, že výsledkem čtení hodnoty bude všude totéž, ale generické typové parametry mohou tento předpoklad zrušit tím, že umožní získat výsledky závislé na typu. + + '{0}' is bound twice in this pattern {0} má v tomto vzoru dvě vazby. @@ -1557,31 +1567,6 @@ Následující pole vyžadují hodnoty: {0} - - Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Omezení hodnoty. Hodnota {0} je obecného typu\n {1}. \nBuď změňte argumenty pro {2} na explicitní, nebo (pokud hodnota nemá být obecná) přidejte poznámku typu. - - - - Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Omezení hodnoty. Hodnota {0} je obecného typu\n {1}. \nZměňte {2} na funkci s explicitními argumenty nebo (pokud hodnota nemá být obecná) přidejte poznámku typu. - - - - Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved. - Omezení hodnoty. Tento člen se odvodil jako člen obecného typu\n {0}. \nKonstruktory a metody getter nebo setter vlastnosti nemůžou být obecnější než nadřazený typ. Přidejte poznámku typu, abyste přesně určili, které typy se mají zahrnout. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Omezení hodnoty. Hodnota {0} se odvodila jako hodnota obecného typu\n {1}. \nBuď změňte argumenty pro {2} na explicitní, nebo (pokud hodnota nemá být obecná) přidejte poznámku typu. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Omezení hodnoty. Hodnota {0} se odvodila jako hodnota obecného typu\n {1}. \nDefinujte {2} jako jednoduchý datový výraz, změňte ji na funkci s explicitními argumenty nebo (pokud hodnota nemá být obecná) přidejte poznámku typu. - - syntax error chyba syntaxe diff --git a/src/Compiler/xlf/FSStrings.de.xlf b/src/Compiler/xlf/FSStrings.de.xlf index 3178a6def03..af3480d9391 100644 --- a/src/Compiler/xlf/FSStrings.de.xlf +++ b/src/Compiler/xlf/FSStrings.de.xlf @@ -44,12 +44,12 @@ Non-static member is expected. - Non-static member is expected. + Ein nicht statischer Member wird erwartet. Static member is expected. - Static member is expected. + Ein statischer Member wird erwartet. @@ -227,6 +227,16 @@ Die Felder "{0}" und "{1}" stammen aus unterschiedlichen Typen. + + Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x<'a>".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Werteinschränkung: Der Wert "{0}" weist einen abgeleiteten generischen Typ auf.\n {1}\nWerte dürfen jedoch keine generischen Typvariablen wie "_a" in "let x: "_a" aufweisen. Sie können eine der folgenden Aktionen ausführen:\n– Definieren Sie ihn als einfachen Datenausdruck wie ein ganzzahliges Literal, ein Zeichenfolgenliteral oder einen Union-Fall wie "let x = 1"\n– Fügen Sie eine explizite Typanmerkung wie "let x : int" hinzu.\n– Verwenden Sie den Wert als nicht generischen Typ im späteren Code für Typrückschlüsse wie "do x"\noder wenn Sie weiterhin typabhängige Ergebnisse wünschen, können Sie "{2}" stattdessen als Funktion definieren, indem Sie einen der folgenden Schritte ausführen:\n– Fügen Sie einen Einheitenparameter wie "let x()" hinzu.\n– Schreiben Sie explizite Typparameter wie "let x<'a>".\nDieser Fehler liegt daran, dass eine let-Bindung ohne Parameter einen Wert definiert, keine Funktion. Werte können nicht generisch sein, da davon ausgegangen wird, dass das Lesen eines Werts überall zum selben Ergebnis führt, generische Typparameter diese Annahme jedoch möglicherweise ungültig machen, indem typabhängige Ergebnisse aktiviert werden. + + + + Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f<'a>"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -> obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Werteinschränkung: Der Wert "{0}" weist einen abgeleiteten generischen Funktionstyp auf.\n {1}\nWerte dürfen jedoch keine generischen Typvariablen wie "_a" in "let f: "_a" aufweisen. Sie sollten stattdessen "{2}" als Funktion definieren, indem Sie einen der folgenden Schritte ausführen:\n– Fügen Sie einen expliziten Parameter hinzu, der angewendet wird, anstatt eine partielle Anwendung "let f param" zu verwenden.\n– Fügen Sie einen Einheitenparameter wie "let f()" hinzu.\n– Schreiben Sie explizite Typparameter wie "let f<'a>",\n oder wenn Sie nicht beabsichtigen, dass er generisch ist, entweder:\n– Fügen Sie eine explizite Typanmerkung wie "let f : obj -> obj" hinzu.\n– Wenden Sie Argumente nicht generischer Typen auf den Funktionswert im späteren Code für Typrückschlüsse wie "do f()" an.\nDieser Fehler liegt daran, dass eine Let-Bindung ohne Parameter einen Wert definiert, keine Funktion. Werte können nicht generisch sein, da davon ausgegangen wird, dass das Lesen eines Werts überall zum selben Ergebnis führt, generische Typparameter diese Annahme jedoch möglicherweise ungültig machen, indem typabhängige Ergebnisse aktiviert werden. + + '{0}' is bound twice in this pattern {0} ist in diesem Muster doppelt gebunden. @@ -1557,31 +1567,6 @@ Für die folgenden Felder sind Werte erforderlich: {0} - - Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Werteinschränkung. Der Wert "{0}" hat den generischen Typ\n {1} \nLegen Sie die Argumente für "{2}" entweder als explizit fest, oder fügen Sie eine Typanmerkung hinzu, wenn der Typ nicht generisch sein soll. - - - - Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Werteinschränkung. Der Wert "{0}" hat den generischen Typ\n {1} \nDefinieren Sie "{2}" entweder als Funktion mit expliziten Argumenten, oder fügen Sie eine Typanmerkung hinzu, wenn der Typ nicht generisch sein soll. - - - - Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved. - Werteinschränkung. Dieser Member wurde per Rückschluss abgeleitet als generischer Typ\n {0} \nKonstruktoren und Eigenschaftengetter/-setter dürfen nicht generischer sein als der einschließende Typ. Fügen Sie eine Typanmerkung hinzu, um die genauen Typen anzugeben. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Werteinschränkung. Der Wert "{0}" wurde per Rückschluss abgeleitet als generischer Typ\n {1} \nLegen Sie die Argumente für "{2}" entweder als explizit fest, oder fügen Sie eine Typanmerkung hinzu, wenn der Typ nicht generisch sein soll. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Werteinschränkung. Der Wert "{0}" wurde per Rückschluss abgeleitet als generischer Typ\n {1} \nDefinieren Sie "{2}" entweder als einfachen Ausdruck oder als Funktion mit expliziten Argumenten, oder fügen Sie eine Typanmerkung hinzu, wenn der Typ nicht generisch sein soll. - - syntax error Syntaxfehler diff --git a/src/Compiler/xlf/FSStrings.es.xlf b/src/Compiler/xlf/FSStrings.es.xlf index 7b2e668ea61..15af13cdb29 100644 --- a/src/Compiler/xlf/FSStrings.es.xlf +++ b/src/Compiler/xlf/FSStrings.es.xlf @@ -44,12 +44,12 @@ Non-static member is expected. - Non-static member is expected. + Se espera un miembro no estático. Static member is expected. - Static member is expected. + Se espera un miembro estático. @@ -227,6 +227,16 @@ Los campos '{0}' y '{1}' son de tipos diferentes. + + Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x<'a>".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Restricción de valor: el valor '{0}' tiene un tipo genérico inferido\n {1}\nSin embargo, los valores no pueden tener variables de tipo genérico como '_a en "let x: '_a". Puede realizar una de las siguientes acciones:\n- Definirlo como un término de datos simple como un literal entero, un literal de cadena o un caso de unión como "let x = 1"\n- Agregar una anotación de tipo explícito como "let x : int"\n- Usar el valor como un tipo no genérico en código posterior para la inferencia de tipos como "do x"\no si aún desea resultados dependientes de tipos, puede definir '{2}' como una función en su lugar haciendo lo siguiente:\n- Agregar un parámetro de unidad como "let x()"\n- Escribir parámetros de tipo explícito como "let x<'a>".\nEste error se debe a que un enlace let sin parámetros define un valor, no una función. Los valores no pueden ser genéricos porque se supone que la lectura de un valor da como resultado lo mismo en todas partes, pero los parámetros de tipo genérico pueden invalidar esta suposición habilitando resultados dependientes de tipos. + + + + Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f<'a>"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -> obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Restricción de valor: el valor '{0}' tiene un tipo de función genérica inferida\n {1}\nSin embargo, los valores no pueden tener variables de tipo genérico como '_a en "let f: '_a". Para definir '{2}' como una función, realice una de las siguientes acciones:\n- Agregue un parámetro explícito que se aplique en lugar de usar una aplicación parcial "let f param"\n- Agregue un parámetro de unidad como "let f()"\n- Escriba parámetros de tipo explícito como "let f<'a>"\no si no pretende que sea genérico, puede:\n- Agregar una anotación de tipo explícito como "let f : obj -> obj"\n- Aplicar argumentos de tipos no genéricos al valor de función en código posterior para la inferencia de tipos como "do f()".\nEste error se debe a que un enlace let sin parámetros define un valor, no una función. Los valores no pueden ser genéricos porque se supone que la lectura de un valor da como resultado lo mismo en todas partes, pero los parámetros de tipo genérico pueden invalidar esta suposición habilitando resultados dependientes de tipos. + + '{0}' is bound twice in this pattern '{0}' está enlazado dos veces en este patrón @@ -1557,31 +1567,6 @@ Los campos siguientes requieren valores: {0}. - - Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Restricción de valor. El valor '{0}' tiene el tipo genérico\n {1} \nConvierta los argumentos de '{2}' en explícitos o, si su intención no es que sea genérico, agregue una anotación de tipo. - - - - Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Restricción de valor. El valor '{0}' tiene el tipo genérico\n {1} \nConvierta '{2}' en una función con argumentos explícitos o, si su intención no es que sea genérico, agregue una anotación de tipo. - - - - Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved. - Restricción de valor. Se ha inferido que este miembro tiene el tipo genérico\n {0} \nLos constructores y los captadores y establecedores de propiedades no pueden ser más genéricos que el tipo envolvente. Agregue una anotación de tipo para indicar los tipos exactos implicados. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Restricción de valor. Se ha inferido que el valor '{0}' tiene el tipo genérico\n {1} \nConvierta los argumentos de '{2}' en explícitos o, si su intención no es que sea genérico, agregue una anotación de tipo. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Restricción de valor. Se ha inferido que el valor '{0}' tiene el tipo genérico\n {1} \nDefina '{2}' como un término de datos simple, conviértalo en una función con argumentos explícitos o, si su intención no es que sea genérico, agregue una anotación de tipo. - - syntax error error de sintaxis diff --git a/src/Compiler/xlf/FSStrings.fr.xlf b/src/Compiler/xlf/FSStrings.fr.xlf index 35581a00f2d..4aaed1d6687 100644 --- a/src/Compiler/xlf/FSStrings.fr.xlf +++ b/src/Compiler/xlf/FSStrings.fr.xlf @@ -44,12 +44,12 @@ Non-static member is expected. - Non-static member is expected. + Un membre non statique est attendu. Static member is expected. - Static member is expected. + Un membre statique est attendu. @@ -227,6 +227,16 @@ Les champs '{0}' et '{1}' sont de types différents + + Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x<'a>".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Restriction de valeur : La valeur '{0}' a un type générique déduit\n {1}\nCependant, les valeurs ne peuvent pas avoir de variables de type générique comme '_a dans "let x: '_a". Vous pouvez effectuer l'une des opérations suivantes :\n- Le définir comme un terme de données simple comme un littéral entier, un littéral de chaîne ou un cas d'union comme "let x = 1"\n- Ajouter une annotation de type explicite comme "let x : int"\n- Utilisez la valeur comme type non générique dans le code ultérieur pour l'inférence de type comme "do x"\ni si vous souhaitez toujours des résultats dépendants du type, vous pouvez définir '{2}' comme fonction à la place en faisant soit :\n- Ajoutez un paramètre d'unité comme "let x()"\n- Écrivez des paramètres de type explicites comme "let x<'a>".\nCette erreur est due au fait qu'une liaison let sans paramètres définit une valeur, pas une fonction. Les valeurs ne peuvent pas être génériques car la lecture d'une valeur est supposée donner le même résultat partout, mais les paramètres de type génériques peuvent invalider cette hypothèse en permettant des résultats dépendants du type. + + + + Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f<'a>"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -> obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Restriction de valeur : La valeur '{0}' a un type de fonction générique déduit\n {1}\nCependant, les valeurs ne peuvent pas avoir de variables de type générique comme '_a dans "let f: '_a". Vous devez plutôt définir '{2}' comme fonction en effectuant l'une des opérations suivantes :\n- Ajouter un paramètre explicite qui est appliqué au lieu d'utiliser une application partielle "let f param"\n- Ajouter un paramètre d'unité comme "let f() "\n- Écrivez des paramètres de type explicites comme "let f<'a>"\ni si vous ne souhaitez pas qu'ils soient génériques, soit :\n- Ajoutez une annotation de type explicite comme "let f : obj -> obj" \n- Appliquer des arguments de types non génériques à la valeur de la fonction dans le code ultérieur pour l'inférence de type comme "do f()".\nCette erreur est due au fait qu'une liaison let sans paramètres définit une valeur, pas une fonction. Les valeurs ne peuvent pas être génériques car la lecture d'une valeur est supposée donner le même résultat partout, mais les paramètres de type génériques peuvent invalider cette hypothèse en permettant des résultats dépendants du type. + + '{0}' is bound twice in this pattern '{0}' est lié à deux reprises dans ce modèle @@ -1557,31 +1567,6 @@ Les champs suivants requièrent des valeurs : {0} - - Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Restriction de valeur. La valeur '{0}' a le type générique\n {1} \nRendez les arguments de '{2}' explicites ou, si votre but n'est pas d'utiliser un type générique, ajoutez une annotation de type. - - - - Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Restriction de valeur. La valeur '{0}' a le type générique\n {1} \nChangez '{2}' en fonction avec des arguments explicites ou, si votre but n'est pas d'utiliser un type générique, ajoutez une annotation de type. - - - - Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved. - Restriction de valeur. Il a été déduit que ce membre avait un type générique\n {0} \nLes constructeurs, ainsi que les méthodes getter/setter d'une propriété ne peuvent pas être plus génériques que le type englobant. Ajoutez une annotation de type pour indiquer les types exacts impliqués. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Restriction de valeur. Il a été déduit que la valeur '{0}' avait le type générique\n {1} \nRendez les arguments de '{2}' explicites ou, si votre but n'est pas d'utiliser un type générique, ajoutez une annotation de type. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Restriction de valeur. Il a été déduit que la valeur '{0}' avait le type générique\n {1} \nDéfinissez '{2}' en tant que terme de données simple, faites-en une fonction avec des arguments explicites ou, si votre but n'est pas d'utiliser un type générique, ajoutez une annotation de type. - - syntax error erreur de syntaxe diff --git a/src/Compiler/xlf/FSStrings.it.xlf b/src/Compiler/xlf/FSStrings.it.xlf index 5fc7bbeeec9..946b68dfe57 100644 --- a/src/Compiler/xlf/FSStrings.it.xlf +++ b/src/Compiler/xlf/FSStrings.it.xlf @@ -44,12 +44,12 @@ Non-static member is expected. - Non-static member is expected. + È previsto un membro non statico. Static member is expected. - Static member is expected. + È previsto un membro statico. @@ -227,6 +227,16 @@ I campi '{0}' e '{1}' sono di tipi diversi + + Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x<'a>".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Restrizione del valore: il valore '{0}' ha un tipo generico dedotta\n {1}\nTuttavia, i valori non possono avere variabili di tipo generico come '_a in "let x: '_a". È possibile eseguire una delle operazioni seguenti:\n- Definirlo come termine di dati semplice come un valore letterale integer, un valore letterale stringa o un case di unione come "let x = 1"\n- Aggiungere un'annotazione di tipo esplicito come "let x : int"\n- Usare il valore come tipo non generico nel codice successivo per l'inferenza del tipo come "do x"\noppure se si vogliono ancora risultati dipendenti dal tipo, è possibile definire '{2}' come funzione eseguendo una delle operazioni seguenti:\n- Aggiungere un parametro di unità come "let x()"\n- Scrivere parametri di tipo esplicito come "let x<'a>".\nQuesto errore è dovuto al fatto che un'associazione let senza parametri definisce un valore, non una funzione. I valori non possono essere generici, perché si presuppone che la lettura di un valore restituisca lo stesso risultato ovunque, ma i parametri di tipo generico possono invalidare questa ipotesi, consentendo risultati dipendenti dal tipo. + + + + Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f<'a>"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -> obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Restrizione del valore: il valore '{0}' ha un tipo di funzione generica dedotta\n {1}\nTuttavia, i valori non possono avere variabili di tipo generico come '_a in "let f: '_a". È consigliabile definire '{2}' come funzione eseguendo una delle operazioni seguenti:\n- aggiungere un parametro esplicito applicato invece di usare un'applicazione parziale "let f param"\n- Aggiungere un parametro di unità come "let f()"\n- Scrivere parametri di tipo esplicito come "let f<'a>"\no se non si vuole che sia generico, o:\n- Aggiungere un'annotazione di tipo esplicito come "let f : obj -> obj"\n- Applicare argomenti di tipi non generici al valore della funzione nel codice successivo per l'inferenza del tipo come "do f()".\nQuesto errore è dovuto al fatto che un'associazione let senza parametri definisce un valore, non una funzione. I valori non possono essere generici, perché si presuppone che la lettura di un valore restituisca lo stesso risultato ovunque, ma i parametri di tipo generico possono invalidare questa ipotesi, consentendo risultati dipendenti dal tipo. + + '{0}' is bound twice in this pattern '{0}' è associato due volte in questo criterio @@ -1557,31 +1567,6 @@ Immissione valori obbligatoria per i campi seguenti: {0} - - Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Limitazione valore. Il valore '{0}' ha il tipo generico\n {1} \nRendere gli argomenti di '{2}' espliciti oppure, se non si intende renderlo generico, aggiungere un'annotazione di tipo. - - - - Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Limitazione valore. Il valore '{0}' ha il tipo generico\n {1} \nRendere '{2}' una funzione con argomenti espliciti oppure, se non si intende renderlo generico, aggiungere un'annotazione di tipo. - - - - Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved. - Restrizione relativa ai valori. È stato dedotto che il membro ha il tipo generico\n {0} \nI getter/setter di proprietà e i costruttori non possono essere più generici del tipo di inclusione. Aggiungere un'annotazione di tipo per indicare i tipi esatti previsti. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Limitazione valore. È stato dedotto che il valore '{0}' ha il tipo generico\n {1} \nRendere gli argomenti di '{2}' espliciti, oppure se non si intende renderlo generico, aggiungere un'annotazione di tipo. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Limitazione valore. È stato dedotto che il valore '{0}' ha il tipo generico\n {1} \nDefinire '{2}' come termine di dati semplice, renderlo una funzione con argomenti espliciti oppure, se non si intende renderlo generico, aggiungere un'annotazione di tipo. - - syntax error errore di sintassi diff --git a/src/Compiler/xlf/FSStrings.ja.xlf b/src/Compiler/xlf/FSStrings.ja.xlf index 103a4edeca0..f5f2df9a156 100644 --- a/src/Compiler/xlf/FSStrings.ja.xlf +++ b/src/Compiler/xlf/FSStrings.ja.xlf @@ -44,12 +44,12 @@ Non-static member is expected. - Non-static member is expected. + 静的でないメンバーが必要です。 Static member is expected. - Static member is expected. + 静的メンバーが必要です。 @@ -227,6 +227,16 @@ フィールド '{0}' と '{1}' は異なる型です + + Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x<'a>".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + 値の制限: 値 '{0}' は推論されたジェネリック関数 \n {1}\n を持ちますが、 "let x: '_a" で '_a のようなジェネリック型変数を持つことはできません。次のいずれかを実行できます。①整数リテラル、文字列リテラル、または "let x = 1"\n- のような共用体ケースを簡易データ項目として定義する。②"let x : int"\n- のような明示的な型の注釈を追加する。③型依存型の結果が必要な場合は、"do x"\nor などの型の推定のためにジェネリック型以外として後のコードで使用して、:\n- のいずれかを実行する代わりに関数として '{2}' を定義できます。④"let x()"\n- のような単位パラメーターを追加する。⑤"let x<'a>".\n のような明示的な型パラメーターを記述する。このエラーは、\nパラメーターのない let バインディングが関数ではなく値を定義するため発生します。値を読み取るとどこでも同じ結果になると想定されるため、値をジェネリックにすることはできませんが、ジェネリック型パラメーターは型依存の結果を有効にすることで、この想定が無効になる可能性があります。 + + + + Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f<'a>"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -> obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + 値の制限: 値 '{0}' は推論されたジェネリック関数型 \n {1}\n を持ちますが、"let f: '_a" で '_a のようなジェネリック型変数を持つことはできません。次のいずれかを実行する代わりに、'{2}' を関数として定義する必要があります。①"let f param"\n- のような部分的な適用ではなく、\n適用される明示的なパラメーターを追加する。②"let f()"\n- のような単位パラメーターを追加する。③ジェネリック型であることを意図しない場合は、"let f<'a>"\nor のような明示的な型パラメーターを記述する。④"let f : obj -> obj"\n- のような明示的な型の注釈を追加する。⑤"do f()".\n のような型の推定のために、ジェネリック型でない引数を後のコードで関数値に適用する。このエラーは、\nパラメーターのない let バインディングが関数ではなく値を定義するため発生します。値を読み取るとどこでも同じ結果になると想定されるため、値をジェネリックにすることはできませんが、ジェネリック型パラメーターは型依存の結果を有効にすることで、この想定が無効になる可能性があります。 + + '{0}' is bound twice in this pattern このパターンで '{0}' が 2 回バインドされています @@ -1557,31 +1567,6 @@ 次のフィールドには値が必要です: {0} - - Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - 値の制限。値 '{0}' は次のジェネリック型です。\n {1} \n明示的に引数を '{2}' にするか、ジェネリックにする意図がない場合は型の注釈を追加してください。 - - - - Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - 値の制限。値 '{0}' は次のジェネリック型です。\n {1} \n明示的な引数を使用して '{2}' を関数にするか、ジェネリックにする意図がない場合は型の注釈を追加してください。 - - - - Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved. - 値の制限。このメンバーは次のジェネリック型を持つと推論されました。\n {0} \nコンストラクターとプロパティのゲッター/セッターは、それを囲む型よりも総称性を高くすることができません。関係する正確な型を示すために、型の注釈を追加してください。 - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - 値の制限。値 '{0}' は次のジェネリック型を持つと推論されました。\n {1} \n明示的に引数を '{2}' にするか、ジェネリックにする意図がない場合は型の注釈を追加してください。 - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - 値の制限。値 '{0}' は次のジェネリック型を持つと推論されました。\n {1} \n単純なデータ用語として '{2}' を定義するか、明示的な引数を使用して関数にするか、ジェネリックにする意図がない場合は型の注釈を追加してください。 - - syntax error 構文エラーです diff --git a/src/Compiler/xlf/FSStrings.ko.xlf b/src/Compiler/xlf/FSStrings.ko.xlf index 812dcd965b2..0960b7b3e26 100644 --- a/src/Compiler/xlf/FSStrings.ko.xlf +++ b/src/Compiler/xlf/FSStrings.ko.xlf @@ -44,12 +44,12 @@ Non-static member is expected. - Non-static member is expected. + 비정적 멤버가 필요합니다. Static member is expected. - Static member is expected. + 정적 멤버가 필요합니다. @@ -227,6 +227,16 @@ {0}' 필드와 '{1}' 필드의 소스 형식이 서로 다릅니다. + + Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x<'a>".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + 값 제한: 값 '{0}'에 유추된 제네릭 형식이 있습니다.\n {1}\n하지만 값은 "let x: '_a"의 '_a와 같은 제네릭 형식 변수를 가질 수 없습니다. 다음 중 하나를 수행할 수 있습니다.\n- 정수 리터럴, 문자열 리터럴 또는 "let x = 1"과 같은 공용 구조체 대/소문자와 같은 간단한 데이터 용어로 정의합니다.\n- "let x : int"와 같은 명시적 형식 주석을 추가합니다.\n- "do x"와 같은 형식 유추를 위해 이후 코드에서 값을 제네릭이 아닌 형식으로 사용합니다.\n또는 여전히 형식 종속 결과를 원할 경우 다음 중 하나를 수행하여 '{2}'을(를) 함수로 정의할 수 있습니다.\n- "let x()"와 같은 단위 매개 변수를 추가합니다.\n- "let x<'a>"와 같은 명시적 형식 매개 변수를 작성합니다.\n이 오류는 매개 변수가 없는 let 바인딩이 함수가 아니라 값을 정의하기 때문입니다. 값을 읽으면 모든 위치에서 동일한 결과가 발생하는 것으로 가정되지만 제네릭 형식 매개 변수가 형식 종속 결과를 사용하여 이 가정을 무효화할 수 있기 때문에 값은 제네릭일 수 없습니다. + + + + Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f<'a>"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -> obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + 값 제한: 값 '{0}'에 유추된 제네릭 함수 형식이 있습니다.\n {1}\n하지만 값은 "let f: '_a"의 '_a와 같은 제네릭 형식 변수를 가질 수 없습니다. 대신 다음 중 하나를 수행하여 '{2}'을(를) 함수로 정의해야 합니다.\n- 부분 애플리케이션 "let f param"을 사용하는 대신 적용되는 명시적 매개 변수를 추가합니다.\n- "let f()"와 같은 단위 매개 변수를 추가합니다.\n- "let f<'a>"와 같은 명시적 형식 매개 변수를 작성합니다.\n또는 제네렉이 되지 않게 하려는 경우.\n- "let f : obj -> obj"와 같은 명시적 형식 주석을 추가하거나\n- "do f()"와 같은 형식 유추를 위해 이후 코드의 함수 값에 제네릭이 아닌 형식의 인수를 적용합니다.\n이 오류는 매개 변수가 없는 let 바인딩이 함수가 아니라 값을 정의하기 때문입니다. 값을 읽으면 모든 위치에서 동일한 결과가 발생하는 것으로 가정되지만 제네릭 형식 매개 변수가 형식 종속 결과를 사용하여 이 가정을 무효화할 수 있기 때문에 값은 제네릭일 수 없습니다. + + '{0}' is bound twice in this pattern '{0}'은(는) 이 패턴에서 두 번 바인딩되었습니다. @@ -1557,31 +1567,6 @@ 다음 필드에는 값이 필요합니다. {0} - - Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - 값 제한이 있습니다. 값 '{0}'에 제네릭 형식\n {1}이(가) 있습니다. \n'{2}'에 대한 인수를 명시적으로 만들거나, 제네릭 요소로 만들지 않으려는 경우 형식 주석을 추가하세요. - - - - Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - 값 제한이 있습니다. 값 '{0}'에 제네릭 형식\n {1}이(가) 있습니다. \n'{2}'을(를) 명시적 인수가 포함된 함수로 만들거나, 제네릭 요소로 만들지 않으려는 경우 형식 주석을 추가하세요. - - - - Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved. - 값 제한이 있습니다. 이 멤버는 제네릭 형식\n {0}을(를) 가지는 것으로 유추되었습니다. \n생성자 및 속성 getter/setter는 바깥쪽 형식보다 일반적일 수 없습니다. 형식 주석을 추가하여 관련 형식을 정확히 나타내세요. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - 값 제한이 있습니다. 값 '{0}'은(는) 제네릭 형식\n {1}을(를) 가지는 것으로 유추되었습니다. \n'{2}'에 대한 인수를 명시적으로 만들거나, 제네릭 요소로 만들지 않으려는 경우 형식 주석을 추가하세요. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - 값 제한이 있습니다. 값 '{0}'은(는) 제네릭 형식\n {1}을(를) 가지는 것으로 유추되었습니다. \n'{2}'을(를) 단순 데이터 용어로 정의하거나, 명시적 인수가 포함된 함수로 만들거나, 제네릭 요소로 만들지 않으려는 경우 형식 주석을 추가하세요. - - syntax error 구문 오류입니다. diff --git a/src/Compiler/xlf/FSStrings.pl.xlf b/src/Compiler/xlf/FSStrings.pl.xlf index d10f929a4f1..9e12b8cdea1 100644 --- a/src/Compiler/xlf/FSStrings.pl.xlf +++ b/src/Compiler/xlf/FSStrings.pl.xlf @@ -44,12 +44,12 @@ Non-static member is expected. - Non-static member is expected. + Oczekiwano elementu członkowskiego innego niż statyczny. Static member is expected. - Static member is expected. + Oczekiwano statycznego elementu członkowskiego. @@ -227,6 +227,16 @@ Pola „{0}” i „{1}” są polami różnego typu + + Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x<'a>".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Ograniczenie wartości: wartość „{0}” ma wywnioskowany typ ogólny\n {1}\nWartości nie mogą mieć zmiennych typu ogólnego, takich jak „_a w „let x: „_a”. Możesz wykonać jedną z następujących czynności:\n- Zdefiniuj go jako prosty termin danych, taki jak literał liczby całkowitej, literał ciągu lub przypadek unii, taki jak „let x = 1”\n- Dodaj jawną adnotację typu, taką jak „let x : int”\n- Użyj wartości jako typu nie generycznego w późniejszym kodzie dla wnioskowania typu, takiego jak „do x”,\n jeśli nadal chcesz uzyskać wyniki zależne od typu, Można zdefiniować „{2}” jako funkcję, wykonując jedną z następujących czynności:\n- Dodaj parametr jednostkowy, taki jak „let x()”\n- Zapisz jawne parametry typu, takie jak „let x<'a>”.\nTen błąd jest spowodowany tym, że powiązanie let bez parametrów definiuje wartość, a nie funkcję. Wartości nie mogą być ogólne, ponieważ zakłada się, że odczytanie wartości skutkuje tym samym wszędzie, ale parametry typu ogólnego mogą unieważnić to założenie, umożliwiając uzyskanie wyników zależnych od typu. + + + + Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f<'a>"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -> obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Ograniczenie wartości: wartość „{0}” ma wywnioskowany typ funkcji ogólnej\n {1}\nJako wartości nie mogą mieć zmiennych typu ogólnego, takich jak „_a w „let f: '_a”. Zamiast tego należy zdefiniować „{2}” jako funkcję, wykonując jedną z następujących czynności:\n- Dodaj jawny parametr, który jest stosowany zamiast używania częściowej aplikacji „let f param”\n- Dodaj parametr jednostkowy, taki jak „let f()”\n- Zapisz jawne parametry typu, takie jak „let f<'a>”\nor, jeśli nie zamierzasz, aby był ogólny, either:\n- Dodaj jawną adnotację typu, taką jak „let f : obj -> obj”\n- Zastosuj argumenty typów nie generycznych do wartości funkcji w późniejszym kodzie dla wnioskowania typu, takiego jak „do f()”.\nTen błąd jest spowodowany tym, że powiązanie let bez parametrów definiuje wartość, a nie funkcję. Wartości nie mogą być ogólne, ponieważ zakłada się, że odczytanie wartości skutkuje tym samym wszędzie, ale parametry typu ogólnego mogą unieważnić to założenie, umożliwiając uzyskanie wyników zależnych od typu. + + '{0}' is bound twice in this pattern Zmienna „{0}” została powiązana dwa razy w tym wzorcu @@ -1557,31 +1567,6 @@ Następujące pola wymagają wartości: {0} - - Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Ograniczenie wartości. Wartość „{0}” jest wartością typu ogólnego\n {1} \nOkreśl argumenty elementu „{2}” jako jawne lub dodaj adnotację typu, jeśli nie chcesz, aby wartość była ogólna. - - - - Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Ograniczenie wartości. Wartość „{0}” jest wartością typu ogólnego\n {1} \nUstaw element „{2}” jako funkcję z jawnymi argumentami lub dodaj adnotację typu, jeśli nie chcesz, aby wartość była ogólna. - - - - Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved. - Ograniczenie wartości. Wywnioskowano, że ten element członkowski jest elementem typu ogólnego\n {0} \nKonstruktory i metody pobierające/ustawiające właściwości nie mogą być bardziej ogólne niż typ otaczający. Dodaj adnotację typu, aby dokładnie wskazać uwzględnione typy. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Ograniczenie wartości. Wywnioskowano, że wartość „{0}” jest wartością typu ogólnego\n {1} \nOkreśl argumenty elementu „{2}” jako jawne lub dodaj adnotację typu, jeśli nie chcesz, aby wartość była ogólna. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Ograniczenie wartości. Wywnioskowano, że wartość „{0}” jest wartością typu ogólnego\n {1} \nZdefiniuj element „{2}” jako prosty termin danych, określ go jako funkcję z jawnymi argumentami lub dodaj adnotację typu, jeśli nie chcesz, aby wartość była ogólna. - - syntax error błąd składni diff --git a/src/Compiler/xlf/FSStrings.pt-BR.xlf b/src/Compiler/xlf/FSStrings.pt-BR.xlf index 3255d8c404d..10626ad590b 100644 --- a/src/Compiler/xlf/FSStrings.pt-BR.xlf +++ b/src/Compiler/xlf/FSStrings.pt-BR.xlf @@ -44,12 +44,12 @@ Non-static member is expected. - Non-static member is expected. + O membro não estático é esperado. Static member is expected. - Static member is expected. + O membro estático é esperado. @@ -227,6 +227,16 @@ Os campos '{0}' e '{1}' são de tipos diferentes + + Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x<'a>".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Restrição de valor: o valor "{0}" tem um tipo genérico inferido\n {1}\nEntretanto, os valores não podem ter variáveis de tipo genérico como '_a em "let x: '_a". Você pode fazer o seguinte:\n- Defina-o como um termo de dados simples, como um literal inteiro, um literal de cadeia de caracteres ou um caso de união como "let x = 1"\n- Adicionar uma anotação de tipo explícita como "let x : int"\n- Use o valor como um tipo não genérico em código posterior para inferência de tipo como "do x"\ne se você ainda quiser resultados dependentes de tipo, você pode definir "{2}" como uma função fazendo:\n- Adicione um parâmetro de unidade como "let x()"\n- Escreva parâmetros de tipo explícitos como "let x<'a>".\nEsse erro ocorre porque uma ligação let sem parâmetros define um valor, não uma função. Os valores não podem ser genéricos porque se supõe que a leitura de um valor resulte no mesmo em todos os lugares, mas parâmetros de tipo genérico podem invalidar essa suposição habilitando resultados dependentes de tipo. + + + + Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f<'a>"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -> obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Restrição de valor: o valor "{0}" tem um tipo de função genérica inferido\n {1}\nEntretanto, os valores não podem ter variáveis de tipo genérico como '_a em "let f: '_a". Você deve definir "{2}" como uma função seguindo um destes procedimentos:\n- Adicione um parâmetro explícito que é aplicado em vez de usar uma aplicação parcial "let f param"\n- Adicione um parâmetro de unidade como "let f() "\n- Escreva parâmetros de tipo explícitos como "let f<'a>"\ne se você não pretende que seja genérico:\n- Adicione uma anotação de tipo explícita como "let f : obj -> obj" \n- Aplique argumentos de tipos não genéricos ao valor da função em código posterior para inferência de tipo como "do f()".\nEsse erro ocorre porque uma ligação let sem parâmetros define um valor, não uma função. Os valores não podem ser genéricos porque se supõe que a leitura de um valor resulte no mesmo em todos os lugares, mas parâmetros de tipo genérico podem invalidar essa suposição habilitando resultados dependentes de tipo. + + '{0}' is bound twice in this pattern '{0}' é associado duas vezes neste padrão @@ -1557,31 +1567,6 @@ Os campos a seguir requerem valores: {0} - - Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Restrição de valor. O valor '{0}' tem um tipo genérico\n {1} \nTorne os argumentos '{2}' explícitos ou, se sua intenção não for deixá-los genéricos, adicione uma anotação de tipo. - - - - Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Restrição de valor. O valor '{0}' tem um tipo genérico\n {1} \nInsira '{2}' em uma função com argumentos explícitos ou, se você não desejar que ele seja genérico, adicione uma anotação de tipo. - - - - Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved. - Restrição de valor. Este membro foi inferido para ter um tipo genérico\n {0} \nConstrutores e getters/setters de propriedade não podem ser mais genéricos que o tipo de delimitador. Adicione uma anotação de tipo para indicar os tipos exatos envolvidos. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Restrição de valor. O valor '{0}' foi inferido para ter um tipo genérico\n {1} \nTorne os argumentos '{2}' explícitos ou, se sua intenção não for deixá-los genéricos, adicione uma anotação de tipo. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Restrição de valor. O valor '{0}' foi inferido para ter um tipo genérico\n {1} \nDefina '{2}' como um termo de dado simples e torne-o uma função com argumentos explícitos ou, se sua intenção for deixá-los genéricos, adicione uma anotação de tipo. - - syntax error erro de sintaxe diff --git a/src/Compiler/xlf/FSStrings.ru.xlf b/src/Compiler/xlf/FSStrings.ru.xlf index 5de47b70a92..621823ff411 100644 --- a/src/Compiler/xlf/FSStrings.ru.xlf +++ b/src/Compiler/xlf/FSStrings.ru.xlf @@ -44,12 +44,12 @@ Non-static member is expected. - Non-static member is expected. + Ожидается нестатический элемент. Static member is expected. - Static member is expected. + Ожидается статический элемент. @@ -227,6 +227,16 @@ Поля "{0}" и "{1}" принадлежат различным типам + + Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x<'a>".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Ограничение на значение: значение '{0}' имеет предполагаемый универсальный тип\n {1}\nОднако значения не могут иметь переменные универсального типа, такие как '_a в "let x: '_a". Вы можете сделать одно из следующих действий:\n- Определите его как простой термин данных, например целочисленный литерал, строковый литерал или случай объединения, например "let x = 1".\n- Добавьте явную аннотацию типа, например "let x: int"\n- Используйте значение как необобщенный тип в более позднем коде для вывода типа, например "do x"\nили, если вам все еще нужны результаты, зависящие от типа, вы можете вместо этого определить '{2}' как функцию, выполнив одно из следующих действий:\n- Добавьте параметр модуля, например "let x()"\n- Запишите явные параметры типа, например "let x<'a>".\nЭта ошибка связана с тем, что привязка let без параметров определяет значение, а не функцию. Значения не могут быть универсальными, поскольку предполагается, что чтение значения везде приводит к одному и тому же результату, но параметры универсального типа могут сделать это предположение недействительным, включив результаты, зависящие от типа. + + + + Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f<'a>"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -> obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Ограничение значения: значение '{0}' имеет предполагаемый тип универсальной функции\n {1}\nОднако значения не могут иметь переменные универсального типа, такие как '_a в "let f: '_a". Вместо этого вам следует определить '{2}' как функцию, выполнив одно из следующих действий:\n- Добавьте явный параметр, который применяется вместо использования частичного приложения "let f param"\n- Добавьте параметр модуля, например "let f() "\n- Запишите явные параметры типа, например "let f<'a>"\nили, если вы не планируете, чтобы они были универсальными, либо:\n- Добавьте явную аннотацию типа, например "let f : obj -> obj" \n- Применить аргументы неуниверсальных типов к значению функции в более позднем коде для вывода типа, например «do f()».\nЭта ошибка связана с тем, что привязка let без параметров определяет значение, а не функцию. Значения не могут быть универсальными, поскольку предполагается, что чтение значения везде приводит к одному и тому же результату, но параметры универсального типа могут сделать это предположение недействительным, включив результаты, зависящие от типа. + + '{0}' is bound twice in this pattern {0} в данном шаблоне привязан дважды @@ -1557,31 +1567,6 @@ Для следующих полей требуются значения: {0} - - Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Ограничение значения. Значение "{0}" имеет универсальный тип\n {1} \nЛибо сделайте аргументы для "{2}" явными либо (если универсальный тип не требуется) добавьте аннотацию типа. - - - - Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Ограничение значения. Значение "{0}" имеет универсальный тип\n {1} \nЛибо сделайте "{2}" функцией с явными аргументами, либо (если универсальный тип не требуется) добавьте аннотацию типа. - - - - Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved. - Ограничение значения. Данный выведенный элемент должен иметь универсальный тип\n {0} \nМетоды получения или задания свойств и конструкторов не могут быть более универсальными, чем вмещающий тип. Добавьте аннотацию типа, чтобы точно обозначить затрагиваемые типы. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Ограничение значения. Выведенное значение "{0}" должно иметь универсальный тип\n {1} \nЛибо сделайте аргументы для "{2}" явными, либо (если универсальный тип не требуется) добавьте аннотацию типа. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Ограничение значения. Выведенное значение "{0}" должно иметь универсальный тип\n {1} \nЛибо определите "{2}" как простой член данных, либо сделайте его функцией с явными аргументами, либо (если универсальный тип не требуется) добавьте аннотацию типа. - - syntax error синтаксическая ошибка diff --git a/src/Compiler/xlf/FSStrings.tr.xlf b/src/Compiler/xlf/FSStrings.tr.xlf index 1fac64a8dc9..7051cbfd579 100644 --- a/src/Compiler/xlf/FSStrings.tr.xlf +++ b/src/Compiler/xlf/FSStrings.tr.xlf @@ -44,12 +44,12 @@ Non-static member is expected. - Non-static member is expected. + Statik olmayan üye bekleniyor. Static member is expected. - Static member is expected. + Statik üye bekleniyor. @@ -227,6 +227,16 @@ {0}' ve '{1}' alanları farklı türlerde + + Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x<'a>".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Değer kısıtlaması: '{0}' değeri, çıkarsanan bir genel türe sahip\n {1}\nAncak değerlerin "let f: '_a" içinde '_a gibi genel tür değişkenleri olamaz. Şunlardan birini yapabilirsiniz:\n- Tamsayı sabit değeri, dize sabit değeri veya birleşim durumu gibi basit bir veri terimi olarak tanımlayın, örneğin "let x = 1"\n- Açık bir tür ek açıklaması ekleyin, örneğin "let x : int" \n- Tür çıkarımı için değeri sonraki kodda genel olmayan bir tür olarak kullanın, örneğin "do x" \nveya yine de türe bağımlı sonuçlar istiyorsanız, şunlardan birini yaparak '{2}' öğesini işlev olarak tanımlayın:\n- Bir birim parametresi ekleyin, örneğin "let x()"\n- Açık tür parametreleri yazın, örneğin "let x<'a>".\nBu hatanın nedeni parametre içermeyen bir let bağlamasının bir işlevi değil bir değeri tanımlamasıdır. Bir değerin okunmasının her yerde aynı şekilde sonuçlanacağı varsayıldığından değerler genel olamaz, ancak genel tür parametreleri türe bağımlı sonuçları etkinleştirerek bu varsayımı geçersiz yapabilir. + + + + Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f<'a>"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -> obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + Değer kısıtlaması: '{0}' değeri, çıkarsanan bir genel işlev türüne sahip\n {1}\nAncak değerlerin "let f: '_a" içinde '_a gibi genel tür değişkenleri olamaz. Aşağıdakilerden birini yaparak '{2}' öğesini işlev olarak tanımlamanız gerekir:\n- Kısmi bir uygulama kullanmak yerine uygulanan açık bir parametre ekleyin, örneğin "let f param"\n- Bir birim parametresi ekleyin, örneğin "let f()"\n- Açık tür parametreleri yazın, örneğin "let f<'a>"\nveya genel olmasını istemiyorsanız ya:\n- Bir açık tür ek açıklaması ekleyin, örneğin "let f : obj -> obj"\n- Tür çıkarımı için sonraki koddaki işlev değerine genel olmayan türlerin bağımsız değişkenlerini uygulayın, örneğin "do f()".\nBu hatanın nedeni parametre içermeyen bir let bağlamasının bir işlevi değil bir değeri tanımlamasıdır. Bir değerin okunmasının her yerde aynı şekilde sonuçlanacağı varsayıldığından değerler genel olamaz, ancak genel tür parametreleri türe bağımlı sonuçları etkinleştirerek bu varsayımı geçersiz yapabilir. + + '{0}' is bound twice in this pattern '{0}' bu desende iki kez bağlandı @@ -1557,31 +1567,6 @@ Aşağıdaki alanlar için değerler gerekiyor: {0} - - Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Değer kısıtlaması. '{0}' değerinin genel türü:\n {1} \nYa '{2}' bağımsız değişkenlerini açık yapın ya da genel olmasını istemiyorsanız bir tür ek açıklaması ekleyin. - - - - Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Değer kısıtlaması. '{0}' değerinin genel türü:\n {1} \nYa açık bağımsız değişkenlerle '{2}' için işlev dönüşümü yapın ya da genel olmasını istemiyorsanız bir tür ek açıklaması ekleyin. - - - - Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved. - Değer kısıtlaması. Bu üyenin şu genel türü olduğu çıkarıldı\n {0} \nOluşturucular ve özellik alıcıları/ayarlayıcıları kapsayan türden daha genel olamaz. Söz konusu türleri tam olarak belirtmek için bir tür ek açıklaması ekleyin. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - Değer kısıtlaması. '{0}' değerinin şu genel türü olduğu çıkarıldı:\n {1} \nYa '{2}' bağımsız değişkenlerini açık yapın ya da genel olmasını istemiyorsanız bir tür ek açıklaması ekleyin. - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - Değer kısıtlaması. '{0}' değerinin şu genel türü olduğu çıkarıldı:\n {1} \nYa '{2}' tanımını basit veri terimi olarak yaparak onu açık bağımsız değişkenlerle bir işlev yapın ya da genel olmasını istemiyorsanız bir tür ek açıklaması ekleyin. - - syntax error sözdizimi hatası diff --git a/src/Compiler/xlf/FSStrings.zh-Hans.xlf b/src/Compiler/xlf/FSStrings.zh-Hans.xlf index 8f4363d334a..f184c75a630 100644 --- a/src/Compiler/xlf/FSStrings.zh-Hans.xlf +++ b/src/Compiler/xlf/FSStrings.zh-Hans.xlf @@ -44,12 +44,12 @@ Non-static member is expected. - Non-static member is expected. + 应为非静态成员。 Static member is expected. - Static member is expected. + 应为静态成员。 @@ -227,6 +227,16 @@ 字段“{0}”和“{1}”来自不同的类型 + + Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x<'a>".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + 值限制: 值“{0}”具有推断的泛型类型\n {1}\n但是,值不能具有泛型类型变量,如“let x: '_a”中的 '_a。可以执行下列操作之一:\n- 将其定义为简单数据词,如整数文本、字符串文本或联合大小写(如“let x = 1”)\n- 添加显式类型批注(如“let x : int”)\n- 在后面的代码中将该值用作非泛型类型,以进行类型推理(如“do x”)\n如果仍需要依赖类型的结果,可以改为通过执行以下任一操作来定义“{2}”:\n- 添加单元参数(如“let x()”)\n- 编写显式类型参数,如“let x<'a>”。\n此错误是因为没有参数的 let 绑定定义了一个值,而不是函数。值不能是泛型的,因为会假定读取值会导致所有位置都相同,但泛型类型参数可能通过启用依赖类型的结果来使此假设失效。 + + + + Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f<'a>"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -> obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + 值限制: 值“{0}”具有推断的泛型函数类型\n {1}\n但是,值不能具有泛型类型变量,如“let f: '_a”中的 '_a。你应该将“{2}”定义为一个函数,而不是通过以下方式之一进行定义:\n- 添加一个显式参数,以替代使用部分应用“let f param”\n- 添加一个单位参数,如“let f()”\n- 编写显式类型参数,如“let f<'a>”\n如果不打算使其成为泛型的话,则可以选择:\n- 添加显式类型注释,如“let f : obj -> obj”\n- 在后续代码中对非泛型类型的参数应用于函数值以进行类型推断,例如“do f()”。\n此错误是因为没有参数的 let 绑定定义了一个值,而不是函数。值不能是泛型的,因为会假定读取值会导致所有位置都相同,但泛型类型参数可能通过启用依赖类型的结果来使此假设失效。 + + '{0}' is bound twice in this pattern “{0}”在此模式中绑定了两次 @@ -1557,31 +1567,6 @@ 以下字段需要值: {0} - - Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - 值限制。值“{0}”具有泛型类型\n {1} \n使“{2}”的参数成为显式参数,或添加类型批注(如果您不希望它是泛型的)。 - - - - Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - 值限制。值“{0}”具有泛型类型\n {1} \n使“{2}”成为具有显式参数的函数,或添加类型批注(如果您不希望它是泛型的)。 - - - - Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved. - 值限制。已推理出此成员具有泛型类型\n {0} \n构造函数和属性 Getter/Setter 不能比封闭类型更通用。 添加类型批注以指示涉及到的确切类型。 - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - 值限制。已推理出值“{0}”具有泛型类型\n {1} \n使“{2}”的参数成为显式参数,或添加类型批注(如果您不希望它是泛型的)。 - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - 值限制。已推理出值“{0}”具有泛型类型\n {1} \n将“{2}”定义为简单的数据条目,使其成为具有显式参数的函数,或添加类型批注(如果您不希望它是泛型的)。 - - syntax error 语法错误 diff --git a/src/Compiler/xlf/FSStrings.zh-Hant.xlf b/src/Compiler/xlf/FSStrings.zh-Hant.xlf index e5aa888ced3..f7e88f22576 100644 --- a/src/Compiler/xlf/FSStrings.zh-Hant.xlf +++ b/src/Compiler/xlf/FSStrings.zh-Hant.xlf @@ -44,12 +44,12 @@ Non-static member is expected. - Non-static member is expected. + 必須是非靜態成員。 Static member is expected. - Static member is expected. + 必須是靜態成員。 @@ -227,6 +227,16 @@ 欄位 '{0}' 和 '{1}' 來自不同類型 + + Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x<'a>".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + 值限制: 值 '{0}' 具有推斷的函式類型\n {1}\n不過,值不能有泛型類型變數,例如 "let x: '_a" 中的 '_a。您可以執行下列其中一項操作:\n- 將其定義為簡單資料項,例如整數常值、字串常值或聯集,例如 "let x = 1"\n- 新增明確類型註釋,例如 "let x : int"\n- 在稍後的程式碼中使用該值作為非泛型類型,以用於類型推斷,例如 "do x"\n,或者如果您仍然想要類型相依結果,可以改為將 '{2}' 定義為函式,方法是執行以下兩個動作之一:\n- 新增單位參數,例如 "let x()"\n- 寫入明確類型參數,例如 "let x<'a>"。\n此錯誤是因為 let 繫結沒有定義值的參數,而不是函式。值不能是泛型值,因為讀取值會假設在相同位置產生,但泛型類型參數可能透過啟用類型相依結果,使此假設失效。 + + + + Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f<'a>"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -> obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results. + 值限制: 值 '{0}' 具有推斷的泛型函式類型\n {1}\n不過,值不能有泛型類型變數,例如 "let f: '_a" 中的 '_a。您應該改為將 '{2}' 定義為函式,方法是執行以下動作之一:\n- 新增已套用的明確參數,而不是使用部分套用的 "let f param"\n- 新增單位參數,例如 "let f()"\n- 撰寫明確類型參數,例如 "let f<'a>"\n或者如果您不想讓它成為泛型,則執行以下兩個動作之一:\n- 新增明確的類型註釋,例如 "let f : obj -> obj"\n- 在稍後程式碼中將非泛型類型的引數套用至函式值,以用於類型推斷,例如 "do f()"。\n此錯誤是因為 let 繫結沒有定義值的參數,而不是函式。值不能是泛型值,因為讀取值會假設在相同位置產生,但泛型類型參數可能透過啟用類型相依結果,使此假設失效。 + + '{0}' is bound twice in this pattern '{0}' 在這個模式中繫結兩次 @@ -1557,31 +1567,6 @@ 下列欄位需要值: {0} - - Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - 值限制。值 '{0}' 具有泛型類型\n {1} \n請將 '{2}' 的引數設為明確的,或者如果不想將它設為泛型,請加入類型註釋。 - - - - Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - 值限制。值 '{0}' 具有泛型類型\n {1} \n請將 '{2}' 設為具有明確引數的函式,或者如果不想將它設為泛型,請加入類型註釋。 - - - - Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved. - 值限制。這個成員已被推斷為具有泛型類型\n {0} \n建構函式和屬性 getter/setter 不能比封入類型更為泛型。請加入類型註釋,以指示涉及的確切類型。 - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation. - 值限制。值 '{0}' 已被推斷為具有泛型類型\n {1} \n請將 '{2}' 的引數設為明確的,或者如果不想將它設為泛型,請加入類型註釋。 - - - - Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. - 值限制。值 '{0}' 已被推斷為具有泛型類型\n {1} \n請將 '{2}' 定義為簡單資料項、將它設為具有明確引數的函式,或者如果不想將它設為泛型,請加入類型註釋。 - - syntax error 語法錯誤 diff --git a/src/FSharp.Core/Linq.fs b/src/FSharp.Core/Linq.fs index 257dd27edb2..cf7033e09db 100644 --- a/src/FSharp.Core/Linq.fs +++ b/src/FSharp.Core/Linq.fs @@ -59,11 +59,11 @@ module LeafExpressionConverter = |> System.Reflection.MethodInfo.GetMethodFromHandle :?> MethodInfo - let SubstHelperRaw (q:Expr, x:Var[], y:obj[]) : Expr = + let SubstHelperRaw (q:Expr, x:Var array, y:obj array) : Expr = let d = Map.ofArray (Array.zip x y) q.Substitute(fun v -> v |> d.TryFind |> Option.map (fun x -> Expr.Value (x, v.Type))) - let SubstHelper<'T> (q:Expr, x:Var[], y:obj[]) : Expr<'T> = + let SubstHelper<'T> (q:Expr, x:Var array, y:obj array) : Expr<'T> = SubstHelperRaw(q, x, y) |> Expr.Cast let showAll = @@ -390,15 +390,15 @@ module LeafExpressionConverter = let (|NewAnonymousObjectHelperQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (NewAnonymousObjectHelper)) let (|ArrayLookupQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun (x, y) -> LanguagePrimitives.IntrinsicFunctions.GetArray x y)) - //let (|ArrayAssignQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun -> LanguagePrimitives.IntrinsicFunctions.SetArray : int[] -> int -> int -> unit)) + //let (|ArrayAssignQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun -> LanguagePrimitives.IntrinsicFunctions.SetArray : int array -> int -> int -> unit)) //let (|ArrayTypeQ|_|) (ty:System.Type) = if ty.IsArray && ty.GetArrayRank() = 1 then Some (ty.GetElementType()) else None let substHelperMeth = - methodhandleof (fun (x:Expr, y:Var[], z:obj[]) -> SubstHelper (x, y, z)) + methodhandleof (fun (x:Expr, y:Var array, z:obj array) -> SubstHelper (x, y, z)) |> System.Reflection.MethodInfo.GetMethodFromHandle :?> MethodInfo let substHelperRawMeth = - methodhandleof (fun (x:Expr, y:Var[], z:obj[]) -> SubstHelperRaw (x, y, z)) + methodhandleof (fun (x:Expr, y:Var array, z:obj array) -> SubstHelperRaw (x, y, z)) |> System.Reflection.MethodInfo.GetMethodFromHandle :?> MethodInfo @@ -737,7 +737,7 @@ module LeafExpressionConverter = else Reflection.FSharpType.MakeTupleType(argTypes) let argsP = ConvExprsToLinq env args - let rec build ty (argsP: Expression[]) = + let rec build ty (argsP: Expression array) = match Reflection.FSharpValue.PreComputeTupleConstructorInfo ty with | ctorInfo, None -> Expression.New(ctorInfo, argsP) |> asExpr | ctorInfo, Some (nestedTy) -> @@ -879,7 +879,7 @@ module LeafExpressionConverter = | None -> null - and ConvExprsToLinq env es : Expression[] = + and ConvExprsToLinq env es : Expression array = es |> List.map (ConvExprToLinqInContext env) |> Array.ofList and ConvVarToLinq (v: Var) = diff --git a/src/FSharp.Core/Linq.fsi b/src/FSharp.Core/Linq.fsi index 13f3fa4187e..5064de12f55 100644 --- a/src/FSharp.Core/Linq.fsi +++ b/src/FSharp.Core/Linq.fsi @@ -78,14 +78,14 @@ module LeafExpressionConverter = /// /// /// - val SubstHelper: Expr * Var[] * obj[] -> Expr<'T> + val SubstHelper: Expr * Var array * obj array -> Expr<'T> /// /// A runtime helper used to evaluate nested quotation literals. /// /// /// - val SubstHelperRaw: Expr * Var[] * obj[] -> Expr + val SubstHelperRaw: Expr * Var array * obj array -> Expr val internal (|SpecificCallToMethod|_|): System.RuntimeMethodHandle -> (Expr -> (Expr option * Reflection.MethodInfo * Expr list) option) diff --git a/src/FSharp.Core/array.fs b/src/FSharp.Core/array.fs index 73945231ce6..0611a1aebf0 100644 --- a/src/FSharp.Core/array.fs +++ b/src/FSharp.Core/array.fs @@ -24,12 +24,12 @@ module Array = raise (KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) [] - let length (array: _[]) = + let length (array: _ array) = checkNonNull "array" array array.Length [] - let inline last (array: 'T[]) = + let inline last (array: 'T array) = checkNonNull "array" array if array.Length = 0 then @@ -38,7 +38,7 @@ module Array = array.[array.Length - 1] [] - let tryLast (array: 'T[]) = + let tryLast (array: 'T array) = checkNonNull "array" array if array.Length = 0 then @@ -62,7 +62,8 @@ module Array = if count < 0 then invalidArgInputMustBeNonNegative "count" count - let array: 'T[] = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked count + let array: 'T array = + Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked count for i = 0 to Operators.Checked.(-) array.Length 1 do // use checked arithmetic here to satisfy FxCop array.[i] <- value @@ -70,7 +71,7 @@ module Array = array [] - let tryHead (array: 'T[]) = + let tryHead (array: 'T array) = checkNonNull "array" array if array.Length = 0 then @@ -79,12 +80,12 @@ module Array = Some array.[0] [] - let isEmpty (array: 'T[]) = + let isEmpty (array: 'T array) = checkNonNull "array" array array.Length = 0 [] - let tail (array: 'T[]) = + let tail (array: 'T array) = checkNonNull "array" array if array.Length = 0 then @@ -93,13 +94,13 @@ module Array = Microsoft.FSharp.Primitives.Basics.Array.subUnchecked 1 (array.Length - 1) array [] - let empty<'T> : 'T[] = [||] + let empty<'T> : 'T array = [||] [] - let inline blit (source: 'T[]) (sourceIndex: int) (target: 'T[]) (targetIndex: int) (count: int) = + let inline blit (source: 'T array) (sourceIndex: int) (target: 'T array) (targetIndex: int) (count: int) = Array.Copy(source, sourceIndex, target, targetIndex, count) - let concatArrays (arrs: 'T[][]) : 'T[] = + let concatArrays (arrs: 'T array array) : 'T array = let mutable acc = 0 for h in arrs do @@ -118,11 +119,11 @@ module Array = res [] - let concat (arrays: seq<'T[]>) = + let concat (arrays: seq<'T array>) = checkNonNull "arrays" arrays match arrays with - | :? ('T[][]) as ts -> ts |> concatArrays // avoid a clone, since we only read the array + | :? ('T array array) as ts -> ts |> concatArrays // avoid a clone, since we only read the array | _ -> arrays |> Seq.toArray |> concatArrays [] @@ -139,10 +140,12 @@ module Array = arr [] - let collect (mapping: 'T -> 'U[]) (array: 'T[]) : 'U[] = + let collect (mapping: 'T -> 'U array) (array: 'T array) : 'U array = checkNonNull "array" array let len = array.Length - let result = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked<'U[]> len + + let result = + Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked<'U array> len for i = 0 to result.Length - 1 do result.[i] <- mapping array.[i] @@ -150,7 +153,7 @@ module Array = concatArrays result [] - let splitAt index (array: 'T[]) = + let splitAt index (array: 'T array) = checkNonNull "array" array if index < 0 then @@ -178,7 +181,7 @@ module Array = res1, res2 [] - let take count (array: 'T[]) = + let take count (array: 'T array) = checkNonNull "array" array if count < 0 then @@ -193,7 +196,7 @@ module Array = Microsoft.FSharp.Primitives.Basics.Array.subUnchecked 0 count array [] - let takeWhile predicate (array: 'T[]) = + let takeWhile predicate (array: 'T array) = checkNonNull "array" array if array.Length = 0 then @@ -210,7 +213,7 @@ module Array = (comparer: IEqualityComparer<'SafeKey>) ([] projection: 'T -> 'SafeKey) ([] getKey: 'SafeKey -> 'Key) - (array: 'T[]) + (array: 'T array) = let length = array.Length @@ -240,11 +243,11 @@ module Array = res // We avoid wrapping a StructBox, because under 64 JIT we get some "hard" tailcalls which affect performance - let countByValueType (projection: 'T -> 'Key) (array: 'T[]) = + let countByValueType (projection: 'T -> 'Key) (array: 'T array) = countByImpl HashIdentity.Structural<'Key> projection id array // Wrap a StructBox around all keys in case the key type is itself a type using null as a representation - let countByRefType (projection: 'T -> 'Key) (array: 'T[]) = + let countByRefType (projection: 'T -> 'Key) (array: 'T array) = countByImpl RuntimeHelpers.StructBox<'Key>.Comparer (projection >> RuntimeHelpers.StructBox) @@ -252,7 +255,7 @@ module Array = array [] - let countBy (projection: 'T -> 'Key) (array: 'T[]) = + let countBy (projection: 'T -> 'Key) (array: 'T array) = checkNonNull "array" array if typeof<'Key>.IsValueType then @@ -261,13 +264,13 @@ module Array = countByRefType projection array [] - let append (array1: 'T[]) (array2: 'T[]) = + let append (array1: 'T array) (array2: 'T array) = checkNonNull "array1" array1 checkNonNull "array2" array2 let n1 = array1.Length let n2 = array2.Length - let res: 'T[] = + let res: 'T array = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked (n1 + n2) Array.Copy(array1, 0, res, 0, n1) @@ -275,7 +278,7 @@ module Array = res [] - let head (array: 'T[]) = + let head (array: 'T array) = checkNonNull "array" array if array.Length = 0 then @@ -284,9 +287,9 @@ module Array = array.[0] [] - let copy (array: 'T[]) = + let copy (array: 'T array) = checkNonNull "array" array - (array.Clone() :?> 'T[]) // this is marginally faster + (array.Clone() :?> 'T array) // this is marginally faster //let len = array.Length //let res = zeroCreate len //for i = 0 to len - 1 do @@ -303,7 +306,7 @@ module Array = List.toArray list [] - let indexed (array: 'T[]) = + let indexed (array: 'T array) = checkNonNull "array" array let res = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked array.Length @@ -313,14 +316,14 @@ module Array = res [] - let inline iter ([] action) (array: 'T[]) = + let inline iter ([] action) (array: 'T array) = checkNonNull "array" array for i = 0 to array.Length - 1 do action array.[i] [] - let distinct (array: 'T[]) = + let distinct (array: 'T array) = checkNonNull "array" array let temp = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked array.Length let mutable i = 0 @@ -335,10 +338,10 @@ module Array = Microsoft.FSharp.Primitives.Basics.Array.subUnchecked 0 i temp [] - let inline map ([] mapping: 'T -> 'U) (array: 'T[]) = + let inline map ([] mapping: 'T -> 'U) (array: 'T array) = checkNonNull "array" array - let res: 'U[] = + let res: 'U array = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked array.Length for i = 0 to res.Length - 1 do @@ -347,7 +350,7 @@ module Array = res [] - let iter2 action (array1: 'T[]) (array2: 'U[]) = + let iter2 action (array1: 'T array) (array2: 'U array) = checkNonNull "array1" array1 checkNonNull "array2" array2 let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(action) @@ -359,7 +362,7 @@ module Array = f.Invoke(array1.[i], array2.[i]) [] - let distinctBy projection (array: 'T[]) = + let distinctBy projection (array: 'T array) = checkNonNull "array" array let length = array.Length @@ -379,7 +382,7 @@ module Array = Microsoft.FSharp.Primitives.Basics.Array.subUnchecked 0 i temp [] - let map2 mapping (array1: 'T[]) (array2: 'U[]) = + let map2 mapping (array1: 'T array) (array2: 'U array) = checkNonNull "array1" array1 checkNonNull "array2" array2 let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(mapping) @@ -395,7 +398,7 @@ module Array = res [] - let map3 mapping (array1: 'T1[]) (array2: 'T2[]) (array3: 'T3[]) = + let map3 mapping (array1: 'T1 array) (array2: 'T2 array) (array3: 'T3 array) = checkNonNull "array1" array1 checkNonNull "array2" array2 checkNonNull "array3" array3 @@ -413,7 +416,7 @@ module Array = res [] - let mapi2 mapping (array1: 'T[]) (array2: 'U[]) = + let mapi2 mapping (array1: 'T array) (array2: 'U array) = checkNonNull "array1" array1 checkNonNull "array2" array2 let f = OptimizedClosures.FSharpFunc<_, _, _, _>.Adapt(mapping) @@ -429,7 +432,7 @@ module Array = res [] - let iteri action (array: 'T[]) = + let iteri action (array: 'T array) = checkNonNull "array" array let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(action) @@ -437,7 +440,7 @@ module Array = f.Invoke(i, array.[i]) [] - let iteri2 action (array1: 'T[]) (array2: 'U[]) = + let iteri2 action (array1: 'T array) (array2: 'U array) = checkNonNull "array1" array1 checkNonNull "array2" array2 let f = OptimizedClosures.FSharpFunc<_, _, _, _>.Adapt(action) @@ -449,7 +452,7 @@ module Array = f.Invoke(i, array1.[i], array2.[i]) [] - let mapi (mapping: int -> 'T -> 'U) (array: 'T[]) = + let mapi (mapping: int -> 'T -> 'U) (array: 'T array) = checkNonNull "array" array let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(mapping) let res = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked array.Length @@ -470,7 +473,7 @@ module Array = Microsoft.FSharp.Primitives.Basics.Array.mapFoldBack mapping array state [] - let inline exists ([] predicate: 'T -> bool) (array: 'T[]) = + let inline exists ([] predicate: 'T -> bool) (array: 'T array) = checkNonNull "array" array let mutable state = false let mutable i = 0 @@ -482,7 +485,7 @@ module Array = state [] - let inline contains value (array: 'T[]) = + let inline contains value (array: 'T array) = checkNonNull "array" array let mutable state = false let mutable i = 0 @@ -494,7 +497,7 @@ module Array = state [] - let exists2 predicate (array1: _[]) (array2: _[]) = + let exists2 predicate (array1: _ array) (array2: _ array) = checkNonNull "array1" array1 checkNonNull "array2" array2 let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(predicate) @@ -509,7 +512,7 @@ module Array = loop 0 [] - let forall (predicate: 'T -> bool) (array: 'T[]) = + let forall (predicate: 'T -> bool) (array: 'T array) = checkNonNull "array" array let len = array.Length @@ -519,7 +522,7 @@ module Array = loop 0 [] - let forall2 predicate (array1: _[]) (array2: _[]) = + let forall2 predicate (array1: _ array) (array2: _ array) = checkNonNull "array1" array1 checkNonNull "array2" array2 let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(predicate) @@ -537,7 +540,7 @@ module Array = (comparer: IEqualityComparer<'SafeKey>) ([] keyf: 'T -> 'SafeKey) ([] getKey: 'SafeKey -> 'Key) - (array: 'T[]) + (array: 'T array) = let length = array.Length @@ -570,11 +573,11 @@ module Array = result // We avoid wrapping a StructBox, because under 64 JIT we get some "hard" tailcalls which affect performance - let groupByValueType (keyf: 'T -> 'Key) (array: 'T[]) = + let groupByValueType (keyf: 'T -> 'Key) (array: 'T array) = groupByImpl HashIdentity.Structural<'Key> keyf id array // Wrap a StructBox around all keys in case the key type is itself a type using null as a representation - let groupByRefType (keyf: 'T -> 'Key) (array: 'T[]) = + let groupByRefType (keyf: 'T -> 'Key) (array: 'T array) = groupByImpl RuntimeHelpers.StructBox<'Key>.Comparer (keyf >> RuntimeHelpers.StructBox) @@ -582,7 +585,7 @@ module Array = array [] - let groupBy (projection: 'T -> 'Key) (array: 'T[]) = + let groupBy (projection: 'T -> 'Key) (array: 'T array) = checkNonNull "array" array if typeof<'Key>.IsValueType then @@ -591,7 +594,7 @@ module Array = groupByRefType projection array [] - let pick chooser (array: _[]) = + let pick chooser (array: _ array) = checkNonNull "array" array let rec loop i = @@ -605,7 +608,7 @@ module Array = loop 0 [] - let tryPick chooser (array: _[]) = + let tryPick chooser (array: _ array) = checkNonNull "array" array let rec loop i = @@ -619,7 +622,7 @@ module Array = loop 0 [] - let choose (chooser: 'T -> 'U Option) (array: 'T[]) = + let choose (chooser: 'T -> 'U Option) (array: 'T array) = checkNonNull "array" array let mutable i = 0 @@ -637,7 +640,7 @@ module Array = if i <> array.Length then - let chunk1: 'U[] = + let chunk1: 'U array = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked ((array.Length >>> 2) + 1) chunk1.[0] <- first @@ -656,7 +659,7 @@ module Array = i <- i + 1 if i < array.Length then - let chunk2: 'U[] = + let chunk2: 'U array = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked (array.Length - i) count <- 0 @@ -672,7 +675,7 @@ module Array = i <- i + 1 - let res: 'U[] = + let res: 'U array = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked (chunk1.Length + count) Array.Copy(chunk1, res, chunk1.Length) @@ -1071,16 +1074,16 @@ module Array = | count -> filterViaMask maskArray leftOverMask count src [] - let filter predicate (array: _[]) = + let filter predicate (array: _ array) = checkNonNull "array" array Filter.filter predicate array [] - let where predicate (array: _[]) = + let where predicate (array: _ array) = filter predicate array [] - let except (itemsToExclude: seq<_>) (array: _[]) = + let except (itemsToExclude: seq<_>) (array: _ array) = checkNonNull "itemsToExclude" itemsToExclude checkNonNull "array" array @@ -1091,7 +1094,7 @@ module Array = array |> filter cached.Add [] - let partition predicate (array: _[]) = + let partition predicate (array: _ array) = checkNonNull "array" array let res = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked array.Length let mutable upCount = 0 @@ -1119,7 +1122,7 @@ module Array = res1, res2 [] - let find predicate (array: _[]) = + let find predicate (array: _ array) = checkNonNull "array" array let rec loop i = @@ -1133,7 +1136,7 @@ module Array = loop 0 [] - let tryFind predicate (array: _[]) = + let tryFind predicate (array: _ array) = checkNonNull "array" array let rec loop i = @@ -1147,7 +1150,7 @@ module Array = loop 0 [] - let skip count (array: 'T[]) = + let skip count (array: 'T array) = checkNonNull "array" array if count > array.Length then @@ -1160,7 +1163,7 @@ module Array = Microsoft.FSharp.Primitives.Basics.Array.subUnchecked count (array.Length - count) array [] - let skipWhile predicate (array: 'T[]) = + let skipWhile predicate (array: 'T array) = checkNonNull "array" array let mutable i = 0 @@ -1172,27 +1175,27 @@ module Array = | resLen -> Microsoft.FSharp.Primitives.Basics.Array.subUnchecked i resLen array [] - let findBack predicate (array: _[]) = + let findBack predicate (array: _ array) = checkNonNull "array" array Microsoft.FSharp.Primitives.Basics.Array.findBack predicate array [] - let tryFindBack predicate (array: _[]) = + let tryFindBack predicate (array: _ array) = checkNonNull "array" array Microsoft.FSharp.Primitives.Basics.Array.tryFindBack predicate array [] - let findIndexBack predicate (array: _[]) = + let findIndexBack predicate (array: _ array) = checkNonNull "array" array Microsoft.FSharp.Primitives.Basics.Array.findIndexBack predicate array [] - let tryFindIndexBack predicate (array: _[]) = + let tryFindIndexBack predicate (array: _ array) = checkNonNull "array" array Microsoft.FSharp.Primitives.Basics.Array.tryFindIndexBack predicate array [] - let windowed windowSize (array: 'T[]) = + let windowed windowSize (array: 'T array) = checkNonNull "array" array if windowSize <= 0 then @@ -1203,7 +1206,7 @@ module Array = if windowSize > len then empty else - let res: 'T[][] = + let res: 'T array array = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked (len - windowSize + 1) for i = 0 to len - windowSize do @@ -1212,7 +1215,7 @@ module Array = res [] - let chunkBySize chunkSize (array: 'T[]) = + let chunkBySize chunkSize (array: 'T array) = checkNonNull "array" array if chunkSize <= 0 then @@ -1227,7 +1230,7 @@ module Array = else let chunkCount = (len - 1) / chunkSize + 1 - let res: 'T[][] = + let res: 'T array array = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked chunkCount for i = 0 to len / chunkSize - 1 do @@ -1243,7 +1246,7 @@ module Array = res [] - let splitInto count (array: _[]) = + let splitInto count (array: _ array) = checkNonNull "array" array if count <= 0 then @@ -1252,7 +1255,7 @@ module Array = Microsoft.FSharp.Primitives.Basics.Array.splitInto count array [] - let zip (array1: _[]) (array2: _[]) = + let zip (array1: _ array) (array2: _ array) = checkNonNull "array1" array1 checkNonNull "array2" array2 let len1 = array1.Length @@ -1268,7 +1271,7 @@ module Array = res [] - let zip3 (array1: _[]) (array2: _[]) (array3: _[]) = + let zip3 (array1: _ array) (array2: _ array) (array3: _ array) = checkNonNull "array1" array1 checkNonNull "array2" array2 checkNonNull "array3" array3 @@ -1285,7 +1288,7 @@ module Array = res [] - let allPairs (array1: _[]) (array2: _[]) = + let allPairs (array1: _ array) (array2: _ array) = checkNonNull "array1" array1 checkNonNull "array2" array2 let len1 = array1.Length @@ -1313,7 +1316,7 @@ module Array = res.ToArray() [] - let unzip (array: _[]) = + let unzip (array: _ array) = checkNonNull "array" array let len = array.Length let res1 = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked len @@ -1327,7 +1330,7 @@ module Array = res1, res2 [] - let unzip3 (array: _[]) = + let unzip3 (array: _ array) = checkNonNull "array" array let len = array.Length let res1 = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked len @@ -1343,7 +1346,7 @@ module Array = res1, res2, res3 [] - let rev (array: _[]) = + let rev (array: _ array) = checkNonNull "array" array let res = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked array.Length let mutable j = array.Length - 1 @@ -1355,7 +1358,7 @@ module Array = res [] - let fold<'T, 'State> (folder: 'State -> 'T -> 'State) (state: 'State) (array: 'T[]) = + let fold<'T, 'State> (folder: 'State -> 'T -> 'State) (state: 'State) (array: 'T array) = checkNonNull "array" array let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(folder) let mutable state = state @@ -1366,7 +1369,7 @@ module Array = state [] - let foldBack<'T, 'State> (folder: 'T -> 'State -> 'State) (array: 'T[]) (state: 'State) = + let foldBack<'T, 'State> (folder: 'T -> 'State -> 'State) (array: 'T array) (state: 'State) = checkNonNull "array" array let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(folder) let mutable res = state @@ -1377,7 +1380,7 @@ module Array = res [] - let foldBack2<'T1, 'T2, 'State> folder (array1: 'T1[]) (array2: 'T2[]) (state: 'State) = + let foldBack2<'T1, 'T2, 'State> folder (array1: 'T1 array) (array2: 'T2 array) (state: 'State) = checkNonNull "array1" array1 checkNonNull "array2" array2 let f = OptimizedClosures.FSharpFunc<_, _, _, _>.Adapt(folder) @@ -1393,7 +1396,7 @@ module Array = res [] - let fold2<'T1, 'T2, 'State> folder (state: 'State) (array1: 'T1[]) (array2: 'T2[]) = + let fold2<'T1, 'T2, 'State> folder (state: 'State) (array1: 'T1 array) (array2: 'T2 array) = checkNonNull "array1" array1 checkNonNull "array2" array2 let f = OptimizedClosures.FSharpFunc<_, _, _, _>.Adapt(folder) @@ -1407,7 +1410,7 @@ module Array = state - let foldSubRight f (array: _[]) start fin acc = + let foldSubRight f (array: _ array) start fin acc = checkNonNull "array" array let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(f) let mutable res = acc @@ -1417,7 +1420,7 @@ module Array = res - let scanSubLeft f initState (array: _[]) start fin = + let scanSubLeft f initState (array: _ array) start fin = checkNonNull "array" array let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(f) let mutable state = initState @@ -1430,13 +1433,13 @@ module Array = res [] - let scan<'T, 'State> folder (state: 'State) (array: 'T[]) = + let scan<'T, 'State> folder (state: 'State) (array: 'T array) = checkNonNull "array" array let len = array.Length scanSubLeft folder state array 0 (len - 1) [] - let scanBack<'T, 'State> folder (array: 'T[]) (state: 'State) = + let scanBack<'T, 'State> folder (array: 'T array) (state: 'State) = checkNonNull "array" array Microsoft.FSharp.Primitives.Basics.Array.scanSubRight folder array 0 (array.Length - 1) state @@ -1445,7 +1448,7 @@ module Array = [| value |] [] - let pairwise (array: 'T[]) = + let pairwise (array: 'T array) = checkNonNull "array" array if array.Length < 2 then @@ -1454,7 +1457,7 @@ module Array = init (array.Length - 1) (fun i -> array.[i], array.[i + 1]) [] - let reduce reduction (array: _[]) = + let reduce reduction (array: _ array) = checkNonNull "array" array let len = array.Length @@ -1470,7 +1473,7 @@ module Array = res [] - let reduceBack reduction (array: _[]) = + let reduceBack reduction (array: _ array) = checkNonNull "array" array let len = array.Length @@ -1480,7 +1483,7 @@ module Array = foldSubRight reduction array 0 (len - 2) array.[len - 1] [] - let sortInPlaceWith comparer (array: 'T[]) = + let sortInPlaceWith comparer (array: 'T array) = checkNonNull "array" array let len = array.Length @@ -1497,17 +1500,17 @@ module Array = Array.Sort(array, ComparisonIdentity.FromFunction(comparer)) [] - let sortInPlaceBy (projection: 'T -> 'U) (array: 'T[]) = + let sortInPlaceBy (projection: 'T -> 'U) (array: 'T array) = checkNonNull "array" array Microsoft.FSharp.Primitives.Basics.Array.unstableSortInPlaceBy projection array [] - let sortInPlace (array: 'T[]) = + let sortInPlace (array: 'T array) = checkNonNull "array" array Microsoft.FSharp.Primitives.Basics.Array.unstableSortInPlace array [] - let sortWith (comparer: 'T -> 'T -> int) (array: 'T[]) = + let sortWith (comparer: 'T -> 'T -> int) (array: 'T array) = checkNonNull "array" array let result = copy array sortInPlaceWith comparer result @@ -1556,7 +1559,7 @@ module Array = Seq.toArray source [] - let findIndex predicate (array: _[]) = + let findIndex predicate (array: _ array) = checkNonNull "array" array let len = array.Length @@ -1568,7 +1571,7 @@ module Array = go 0 [] - let tryFindIndex predicate (array: _[]) = + let tryFindIndex predicate (array: _ array) = checkNonNull "array" array let len = array.Length @@ -1580,12 +1583,12 @@ module Array = go 0 [] - let permute indexMap (array: _[]) = + let permute indexMap (array: _ array) = checkNonNull "array" array Microsoft.FSharp.Primitives.Basics.Array.permute indexMap array [] - let inline sum (array: ^T[]) : ^T = + let inline sum (array: ^T array) : ^T = checkNonNull "array" array let mutable acc = LanguagePrimitives.GenericZero< ^T> @@ -1595,7 +1598,7 @@ module Array = acc [] - let inline sumBy ([] projection: 'T -> ^U) (array: 'T[]) : ^U = + let inline sumBy ([] projection: 'T -> ^U) (array: 'T array) : ^U = checkNonNull "array" array let mutable acc = LanguagePrimitives.GenericZero< ^U> @@ -1605,7 +1608,7 @@ module Array = acc [] - let inline min (array: _[]) = + let inline min (array: _ array) = checkNonNull "array" array if array.Length = 0 then @@ -1622,7 +1625,7 @@ module Array = acc [] - let inline minBy ([] projection) (array: _[]) = + let inline minBy ([] projection) (array: _ array) = checkNonNull "array" array if array.Length = 0 then @@ -1642,7 +1645,7 @@ module Array = accv [] - let inline max (array: _[]) = + let inline max (array: _ array) = checkNonNull "array" array if array.Length = 0 then @@ -1659,7 +1662,7 @@ module Array = acc [] - let inline maxBy projection (array: _[]) = + let inline maxBy projection (array: _ array) = checkNonNull "array" array if array.Length = 0 then @@ -1679,7 +1682,7 @@ module Array = accv [] - let inline average (array: 'T[]) = + let inline average (array: 'T array) = checkNonNull "array" array if array.Length = 0 then @@ -1693,7 +1696,7 @@ module Array = LanguagePrimitives.DivideByInt< ^T> acc array.Length [] - let inline averageBy ([] projection: 'T -> ^U) (array: 'T[]) : ^U = + let inline averageBy ([] projection: 'T -> ^U) (array: 'T array) : ^U = checkNonNull "array" array if array.Length = 0 then @@ -1707,7 +1710,7 @@ module Array = LanguagePrimitives.DivideByInt< ^U> acc array.Length [] - let inline compareWith ([] comparer: 'T -> 'T -> int) (array1: 'T[]) (array2: 'T[]) = + let inline compareWith ([] comparer: 'T -> 'T -> int) (array1: 'T array) (array2: 'T array) = checkNonNull "array1" array1 checkNonNull "array2" array2 @@ -1732,7 +1735,7 @@ module Array = else 1 [] - let sub (array: 'T[]) (startIndex: int) (count: int) = + let sub (array: 'T array) (startIndex: int) (count: int) = checkNonNull "array" array if startIndex < 0 then @@ -1747,11 +1750,11 @@ module Array = Microsoft.FSharp.Primitives.Basics.Array.subUnchecked startIndex count array [] - let item index (array: _[]) = + let item index (array: _ array) = array.[index] [] - let tryItem index (array: 'T[]) = + let tryItem index (array: 'T array) = checkNonNull "array" array if index < 0 || index >= array.Length then @@ -1760,15 +1763,15 @@ module Array = Some(array.[index]) [] - let get (array: _[]) index = + let get (array: _ array) index = array.[index] [] - let set (array: _[]) index value = + let set (array: _ array) index value = array.[index] <- value [] - let fill (target: 'T[]) (targetIndex: int) (count: int) (value: 'T) = + let fill (target: 'T array) (targetIndex: int) (count: int) (value: 'T) = checkNonNull "target" target if targetIndex < 0 then @@ -1781,7 +1784,7 @@ module Array = target.[i] <- value [] - let exactlyOne (array: 'T[]) = + let exactlyOne (array: 'T array) = checkNonNull "array" array if array.Length = 1 then @@ -1792,7 +1795,7 @@ module Array = invalidArg "array" (SR.GetString(SR.inputSequenceTooLong)) [] - let tryExactlyOne (array: 'T[]) = + let tryExactlyOne (array: 'T array) = checkNonNull "array" array if array.Length = 1 then @@ -1800,7 +1803,7 @@ module Array = else None - let transposeArrays (array: 'T[][]) = + let transposeArrays (array: 'T array array) = let len = array.Length if len = 0 then @@ -1816,7 +1819,7 @@ module Array = (String.Format("array.[{0}]", j)) array.[j].Length - let result: 'T[][] = + let result: 'T array array = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked lenInner for i in 0 .. lenInner - 1 do @@ -1828,15 +1831,15 @@ module Array = result [] - let transpose (arrays: seq<'T[]>) = + let transpose (arrays: seq<'T array>) = checkNonNull "arrays" arrays match arrays with - | :? ('T[][]) as ts -> ts |> transposeArrays // avoid a clone, since we only read the array + | :? ('T array array) as ts -> ts |> transposeArrays // avoid a clone, since we only read the array | _ -> arrays |> Seq.toArray |> transposeArrays [] - let truncate count (array: 'T[]) = + let truncate count (array: 'T array) = checkNonNull "array" array if count <= 0 then @@ -1847,7 +1850,7 @@ module Array = Microsoft.FSharp.Primitives.Basics.Array.subUnchecked 0 count' array [] - let removeAt (index: int) (source: 'T[]) : 'T[] = + let removeAt (index: int) (source: 'T array) : 'T array = checkNonNull "source" source if index < 0 || index >= source.Length then @@ -1865,7 +1868,7 @@ module Array = result [] - let removeManyAt (index: int) (count: int) (source: 'T[]) : 'T[] = + let removeManyAt (index: int) (count: int) (source: 'T array) : 'T array = checkNonNull "source" source if index < 0 || index > source.Length - count then @@ -1883,7 +1886,7 @@ module Array = result [] - let updateAt (index: int) (value: 'T) (source: 'T[]) : 'T[] = + let updateAt (index: int) (value: 'T) (source: 'T array) : 'T array = checkNonNull "source" source if index < 0 || index >= source.Length then @@ -1900,7 +1903,7 @@ module Array = result [] - let insertAt (index: int) (value: 'T) (source: 'T[]) : 'T[] = + let insertAt (index: int) (value: 'T) (source: 'T array) : 'T array = checkNonNull "source" source if index < 0 || index > source.Length then @@ -1920,7 +1923,7 @@ module Array = result [] - let insertManyAt (index: int) (values: seq<'T>) (source: 'T[]) : 'T[] = + let insertManyAt (index: int) (values: seq<'T>) (source: 'T array) : 'T array = checkNonNull "source" source if index < 0 || index > source.Length then @@ -1950,7 +1953,7 @@ module Array = open System.Collections.Concurrent [] - let exists (predicate: 'T -> bool) (array: 'T[]) = + let exists (predicate: 'T -> bool) (array: 'T array) = checkNonNull "array" array Parallel @@ -1965,12 +1968,12 @@ module Array = |> not [] - let forall (predicate: 'T -> bool) (array: 'T[]) = + let forall (predicate: 'T -> bool) (array: 'T array) = // Not exists $condition <==> (opposite of $condition is true forall) exists (predicate >> not) array |> not [] - let tryFindIndex predicate (array: _[]) = + let tryFindIndex predicate (array: _ array) = checkNonNull "array" array let pResult = @@ -1985,11 +1988,11 @@ module Array = pResult.LowestBreakIteration |> Option.ofNullable |> Option.map int [] - let tryFind predicate (array: _[]) = + let tryFind predicate (array: _ array) = array |> tryFindIndex predicate |> Option.map (fun i -> array[i]) [] - let tryPick chooser (array: _[]) = + let tryPick chooser (array: _ array) = checkNonNull "array" array let allChosen = new System.Collections.Concurrent.ConcurrentDictionary<_, _>() @@ -2010,14 +2013,14 @@ module Array = |> Option.bind (fun i -> allChosen[int i]) [] - let choose chooser (array: 'T[]) = + let choose chooser (array: 'T array) = checkNonNull "array" array let inputLength = array.Length - let isChosen: bool[] = + let isChosen: bool array = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked inputLength - let results: 'U[] = + let results: 'U array = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked inputLength let mutable outputLength = 0 @@ -2050,7 +2053,7 @@ module Array = output [] - let collect (mapping: 'T -> 'U[]) (array: 'T[]) : 'U[] = + let collect (mapping: 'T -> 'U array) (array: 'T array) : 'U array = checkNonNull "array" array let inputLength = array.Length @@ -2063,7 +2066,7 @@ module Array = concatArrays result [] - let map (mapping: 'T -> 'U) (array: 'T[]) : 'U[] = + let map (mapping: 'T -> 'U) (array: 'T array) : 'U array = checkNonNull "array" array let inputLength = array.Length @@ -2076,7 +2079,7 @@ module Array = result [] - let mapi mapping (array: 'T[]) = + let mapi mapping (array: 'T array) = checkNonNull "array" array let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(mapping) let inputLength = array.Length @@ -2094,7 +2097,7 @@ module Array = let private maxPartitions = Environment.ProcessorCount // The maximum number of partitions to use let private minChunkSize = 256 // The minimum size of a chunk to be sorted in parallel - let private createPartitionsUpToWithMinChunkSize maxIdxExclusive minChunkSize (array: 'T[]) = + let private createPartitionsUpToWithMinChunkSize maxIdxExclusive minChunkSize (array: 'T array) = [| let chunkSize = match maxIdxExclusive with @@ -2111,13 +2114,13 @@ module Array = yield new ArraySegment<'T>(array, offset, maxIdxExclusive - offset) |] - let private createPartitionsUpTo maxIdxExclusive (array: 'T[]) = + let private createPartitionsUpTo maxIdxExclusive (array: 'T array) = createPartitionsUpToWithMinChunkSize maxIdxExclusive minChunkSize array (* This function is there also as a support vehicle for other aggregations. It is public in order to be called from inlined functions, the benefit of inlining call into it is significant *) [] - let reduceBy (projection: 'T -> 'U) (reduction: 'U -> 'U -> 'U) (array: 'T[]) = + let reduceBy (projection: 'T -> 'U) (reduction: 'U -> 'U -> 'U) (array: 'T array) = checkNonNull "array" array if array.Length = 0 then @@ -2152,7 +2155,7 @@ module Array = finalResult [] - let inline reduce ([] reduction) (array: _[]) = + let inline reduce ([] reduction) (array: _ array) = array |> reduceBy id reduction let inline vFst struct (a, _) = @@ -2162,49 +2165,49 @@ module Array = b [] - let inline minBy ([] projection) (array: _[]) = + let inline minBy ([] projection) (array: _ array) = array |> reduceBy (fun x -> struct (projection x, x)) (fun a b -> if vFst a < vFst b then a else b) |> vSnd [] - let inline min (array: _[]) = + let inline min (array: _ array) = array |> reduce (fun a b -> if a < b then a else b) [] - let inline sumBy ([] projection: 'T -> ^U) (array: 'T[]) : ^U = + let inline sumBy ([] projection: 'T -> ^U) (array: 'T array) : ^U = if array.Length = 0 then LanguagePrimitives.GenericZero else array |> reduceBy projection Operators.Checked.(+) [] - let inline sum (array: ^T[]) : ^T = + let inline sum (array: ^T array) : ^T = array |> sumBy id [] - let inline maxBy projection (array: _[]) = + let inline maxBy projection (array: _ array) = array |> reduceBy (fun x -> struct (projection x, x)) (fun a b -> if vFst a > vFst b then a else b) |> vSnd [] - let inline max (array: _[]) = + let inline max (array: _ array) = array |> reduce (fun a b -> if a > b then a else b) [] - let inline averageBy ([] projection: 'T -> ^U) (array: 'T[]) : ^U = + let inline averageBy ([] projection: 'T -> ^U) (array: 'T array) : ^U = let sum = array |> reduceBy projection Operators.Checked.(+) LanguagePrimitives.DivideByInt sum (array.Length) [] - let inline average (array: 'T[]) = + let inline average (array: 'T array) = array |> averageBy id [] - let zip (array1: _[]) (array2: _[]) = + let zip (array1: _ array) (array2: _ array) = checkNonNull "array1" array1 checkNonNull "array2" array2 let len1 = array1.Length @@ -2232,7 +2235,7 @@ module Array = (comparer: IEqualityComparer<'SafeKey>) ([] keyf: 'T -> 'SafeKey) ([] getKey: 'SafeKey -> 'Key) - (array: 'T[]) + (array: 'T array) = let counts = new ConcurrentDictionary<_, _>( @@ -2268,7 +2271,7 @@ module Array = let mutable finalIdx = 0 let finalResultsLookup = - new Dictionary<'SafeKey, int ref * 'T[]>(capacity = counts.Count, comparer = comparer) + new Dictionary<'SafeKey, int ref * 'T array>(capacity = counts.Count, comparer = comparer) for kvp in counts do let arrayForThisGroup = @@ -2294,7 +2297,7 @@ module Array = finalResults - let groupByValueTypeParallel (keyf: 'T -> 'Key) (array: 'T[]) = + let groupByValueTypeParallel (keyf: 'T -> 'Key) (array: 'T array) = // Is it a bad idea to put floating points as keys for grouping? Yes // But would the implementation fail with KeyNotFound "nan" if we just leave it? Also yes // Here we enforce nan=nan equality to prevent throwing @@ -2310,7 +2313,7 @@ module Array = // Just like in regular Array.groupBy: Wrap a StructBox around all keys in order to avoid nulls // (dotnet doesn't allow null keys in dictionaries) - let groupByRefTypeParallel (keyf: 'T -> 'Key) (array: 'T[]) = + let groupByRefTypeParallel (keyf: 'T -> 'Key) (array: 'T array) = groupByImplParallel RuntimeHelpers.StructBox<'Key>.Comparer (keyf >> RuntimeHelpers.StructBox) @@ -2318,7 +2321,7 @@ module Array = array [] - let groupBy (projection: 'T -> 'Key) (array: 'T[]) = + let groupBy (projection: 'T -> 'Key) (array: 'T array) = checkNonNull "array" array if typeof<'Key>.IsValueType then @@ -2327,12 +2330,12 @@ module Array = groupByRefTypeParallel projection array [] - let iter action (array: 'T[]) = + let iter action (array: 'T array) = checkNonNull "array" array Parallel.For(0, array.Length, (fun i -> action array.[i])) |> ignore [] - let iteri action (array: 'T[]) = + let iteri action (array: 'T array) = checkNonNull "array" array let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(action) Parallel.For(0, array.Length, (fun i -> f.Invoke(i, array.[i]))) |> ignore @@ -2343,7 +2346,7 @@ module Array = Parallel.For(0, count, (fun i -> result.[i] <- initializer i)) |> ignore result - let countAndCollectTrueItems predicate (array: 'T[]) = + let countAndCollectTrueItems predicate (array: 'T array) = checkNonNull "array" array let inputLength = array.Length @@ -2369,7 +2372,7 @@ module Array = trueLength, isTrue [] - let filter predicate (array: 'T[]) = + let filter predicate (array: 'T array) = let trueLength, isTrue = countAndCollectTrueItems predicate array let res = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked trueLength let mutable resIdx = 0 @@ -2382,7 +2385,7 @@ module Array = res [] - let partition predicate (array: 'T[]) = + let partition predicate (array: 'T array) = let trueLength, isTrue = countAndCollectTrueItems predicate array let res1 = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked trueLength @@ -2402,7 +2405,7 @@ module Array = res1, res2 - let private createPartitions (array: 'T[]) = + let private createPartitions (array: 'T array) = createPartitionsUpTo array.Length array let inline pickPivot @@ -2472,7 +2475,7 @@ module Array = let pivotItem = array[pivotIdx] partitionIntoTwo (fun idx -> cmp array[idx] pivotItem) swap orig - let partitionIntoTwoUsingKeys (keys: 'A[]) (orig: ArraySegment<'T>) : ArraySegment<'T> * ArraySegment<'T> = + let partitionIntoTwoUsingKeys (keys: 'A array) (orig: ArraySegment<'T>) : ArraySegment<'T> * ArraySegment<'T> = let array = orig.Array let inline swap i j = @@ -2490,7 +2493,7 @@ module Array = partitionIntoTwo (fun idx -> compare keys[idx] pivotKey) swap orig let inline sortInPlaceHelper - (array: 'T[]) + (array: 'T array) ([] partitioningFunc: ArraySegment<'T> -> ArraySegment<'T> * ArraySegment<'T>) ([] sortingFunc: ArraySegment<'T> -> unit) = @@ -2526,7 +2529,7 @@ module Array = let sortInPlaceWithHelper (partitioningComparer: 'T -> 'T -> int) (sortingComparer: IComparer<'T>) - (inputArray: 'T[]) + (inputArray: 'T array) = let partitioningFunc = partitionIntoTwoUsingComparer partitioningComparer @@ -2535,7 +2538,7 @@ module Array = sortInPlaceHelper inputArray partitioningFunc sortingFunc - let sortKeysAndValuesInPlace (inputKeys: 'TKey[]) (values: 'TValue[]) = + let sortKeysAndValuesInPlace (inputKeys: 'TKey array) (values: 'TValue array) = let partitioningFunc = partitionIntoTwoUsingKeys inputKeys let sortingComparer = LanguagePrimitives.FastGenericComparerCanBeNull<'TKey> @@ -2546,16 +2549,16 @@ module Array = sortInPlaceHelper values partitioningFunc sortingFunc [] - let sortInPlaceWith comparer (array: 'T[]) = + let sortInPlaceWith comparer (array: 'T array) = checkNonNull "array" array let sortingComparer = ComparisonIdentity.FromFunction(comparer) sortInPlaceWithHelper comparer sortingComparer array [] - let sortInPlaceBy (projection: 'T -> 'U) (array: 'T[]) = + let sortInPlaceBy (projection: 'T -> 'U) (array: 'T array) = checkNonNull "array" array - let inputKeys: 'U[] = + let inputKeys: 'U array = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked array.Length let partitions = createPartitions array @@ -2574,7 +2577,7 @@ module Array = sortKeysAndValuesInPlace inputKeys array [] - let sortInPlace (array: 'T[]) = + let sortInPlace (array: 'T array) = checkNonNull "array" array let sortingComparer: IComparer<'T> = @@ -2584,13 +2587,13 @@ module Array = sortInPlaceWithHelper partioningFunc sortingComparer array [] - let sortWith (comparer: 'T -> 'T -> int) (array: 'T[]) = + let sortWith (comparer: 'T -> 'T -> int) (array: 'T array) = let result = copy array sortInPlaceWith comparer result result [] - let sortBy projection (array: 'T[]) = + let sortBy projection (array: 'T array) = checkNonNull "array" array let inputKeys = @@ -2622,7 +2625,7 @@ module Array = sortInPlace result result - let reverseInPlace (array: 'T[]) = + let reverseInPlace (array: 'T array) = let segments = createPartitionsUpTo (array.Length / 2) array let lastIdx = array.Length - 1 diff --git a/src/FSharp.Core/array.fsi b/src/FSharp.Core/array.fsi index 7ac42219058..8a5d51f0c9e 100644 --- a/src/FSharp.Core/array.fsi +++ b/src/FSharp.Core/array.fsi @@ -35,7 +35,7 @@ module Array = /// /// [] - val allPairs: array1: 'T1[] -> array2: 'T2[] -> ('T1 * 'T2)[] + val allPairs: array1: 'T1 array -> array2: 'T2 array -> ('T1 * 'T2) array /// Builds a new array that contains the elements of the first array followed by the elements of the second array. /// @@ -53,7 +53,7 @@ module Array = /// Evaluates to [| 1; 2; 3; 4 |]. /// [] - val append: array1: 'T[] -> array2: 'T[] -> 'T[] + val append: array1: 'T array -> array2: 'T array -> 'T array /// Returns the average of the elements in the array. /// @@ -79,7 +79,7 @@ module Array = /// [] val inline average: - array: ^T[] -> ^T + array: ^T array -> ^T when ^T: (static member (+): ^T * ^T -> ^T) and ^T: (static member DivideByInt: ^T * int -> ^T) and ^T: (static member Zero: ^T) @@ -110,7 +110,7 @@ module Array = /// /// type Foo = { Bar: float } /// - /// let input : Foo[] = [| |] + /// let input : Foo array = [| |] /// /// input |> Array.averageBy (fun foo -> foo.Bar) /// @@ -118,7 +118,7 @@ module Array = /// [] val inline averageBy: - projection: ('T -> ^U) -> array: 'T[] -> ^U + projection: ('T -> ^U) -> array: 'T array -> ^U when ^U: (static member (+): ^U * ^U -> ^U) and ^U: (static member DivideByInt: ^U * int -> ^U) and ^U: (static member Zero: ^U) @@ -154,7 +154,7 @@ module Array = /// After evaluation target contains [| 0; 1; 2; 13; 14; 5 |]. /// [] - val inline blit: source: 'T[] -> sourceIndex: int -> target: 'T[] -> targetIndex: int -> count: int -> unit + val inline blit: source: 'T array -> sourceIndex: int -> target: 'T array -> targetIndex: int -> count: int -> unit /// For each element of the array, applies the given function. Concatenates all the results and return the combined array. /// @@ -167,7 +167,7 @@ module Array = /// /// /// - /// type Foo = { Bar: int[] } + /// type Foo = { Bar: int array } /// /// let input = [| {Bar = [| 1; 2 |]}; {Bar = [| 3; 4 |]} |] /// @@ -185,7 +185,7 @@ module Array = /// Evaluates to [| 1; 2; 3; 4 |] /// [] - val collect: mapping: ('T -> 'U[]) -> array: 'T[] -> 'U[] + val collect: mapping: ('T -> 'U array) -> array: 'T array -> 'U array /// Compares two arrays using the given comparison function, element by element. /// @@ -268,7 +268,7 @@ module Array = /// Evaluates to -1 /// [] - val inline compareWith: comparer: ('T -> 'T -> int) -> array1: 'T[] -> array2: 'T[] -> int + val inline compareWith: comparer: ('T -> 'T -> int) -> array1: 'T array -> array2: 'T array -> int /// Builds a new array that contains the elements of each of the given sequence of arrays. /// @@ -287,7 +287,7 @@ module Array = /// Evaluates to [| 1; 2; 3; 4; 5 |] /// [] - val concat: arrays: seq<'T[]> -> 'T[] + val concat: arrays: seq<'T array> -> 'T array /// Tests if the array contains the specified element. /// @@ -305,7 +305,7 @@ module Array = /// /// [] - val inline contains: value: 'T -> array: 'T[] -> bool when 'T: equality + val inline contains: value: 'T -> array: 'T array -> bool when 'T: equality /// Builds a new array that contains the elements of the given array. /// @@ -324,7 +324,7 @@ module Array = /// Evaluates to a new array containing[| 12; 13; 14 |]. /// [] - val copy: array: 'T[] -> 'T[] + val copy: array: 'T array -> 'T array /// Applies a key-generating function to each element of an array and returns an array yielding unique /// keys and their number of occurrences in the original array. @@ -348,7 +348,7 @@ module Array = /// Evaluates to [| ("a", 2); ("b", 1) |] /// [] - val countBy: projection: ('T -> 'Key) -> array: 'T[] -> ('Key * int)[] when 'Key: equality + val countBy: projection: ('T -> 'Key) -> array: 'T array -> ('Key * int) array when 'Key: equality /// Creates an array whose elements are all initially the given value. /// @@ -378,7 +378,7 @@ module Array = /// Note each entry in the array is the same mutable cell object. /// [] - val create: count: int -> value: 'T -> 'T[] + val create: count: int -> value: 'T -> 'T array /// Returns the first element of the array, or /// None if the array is empty. @@ -400,14 +400,14 @@ module Array = /// /// /// - /// let inputs : int[] = [| |] + /// let inputs : int array = [| |] /// /// inputs |> Array.tryHead /// /// Evaluates to None /// [] - val tryHead: array: 'T[] -> 'T option + val tryHead: array: 'T array -> 'T option /// Applies the given function to successive elements, returning the first /// result where the function returns Some(x) for some x. If the function @@ -439,7 +439,7 @@ module Array = /// /// [] - val tryPick: chooser: ('T -> 'U option) -> array: 'T[] -> 'U option + val tryPick: chooser: ('T -> 'U option) -> array: 'T array -> 'U option /// Fills a range of elements of the array with the given value. /// @@ -460,7 +460,7 @@ module Array = /// After evaluation target contains [| 0; 1; 2; 100; 100; 5 |]. /// [] - val fill: target: 'T[] -> targetIndex: int -> count: int -> value: 'T -> unit + val fill: target: 'T array -> targetIndex: int -> count: int -> value: 'T -> unit /// Applies the given function to successive elements, returning the first /// result where the function returns Some(x) for some x. If the function @@ -494,7 +494,7 @@ module Array = /// /// [] - val pick: chooser: ('T -> 'U option) -> array: 'T[] -> 'U + val pick: chooser: ('T -> 'U option) -> array: 'T array -> 'U /// Applies the given function to each element of the array. Returns /// the array comprised of the results x for each element where @@ -525,7 +525,7 @@ module Array = /// Evaluates to [| 2 |] /// [] - val choose: chooser: ('T -> 'U option) -> array: 'T[] -> 'U[] + val choose: chooser: ('T -> 'U option) -> array: 'T array -> 'U array /// Divides the input array into chunks of size at most chunkSize. /// @@ -555,7 +555,7 @@ module Array = /// Throws ArgumentException /// [] - val chunkBySize: chunkSize: int -> array: 'T[] -> 'T[][] + val chunkBySize: chunkSize: int -> array: 'T array -> 'T array array /// Returns an array that contains no duplicate entries according to generic hash and /// equality comparisons on the entries. @@ -576,7 +576,7 @@ module Array = /// Evaluates to [| 1; 2; 3 |] /// [] - val distinct: array: 'T[] -> 'T[] when 'T: equality + val distinct: array: 'T array -> 'T array when 'T: equality /// Returns an array that contains no duplicate entries according to the /// generic hash and equality comparisons on the keys returned by the given key-generating function. @@ -598,7 +598,7 @@ module Array = /// Evaluates to [| { Bar = 1 }; { Bar = 2 }; { Bar = 3 } |] /// [] - val distinctBy: projection: ('T -> 'Key) -> array: 'T[] -> 'T[] when 'Key: equality + val distinctBy: projection: ('T -> 'Key) -> array: 'T array -> 'T array when 'Key: equality /// Splits the input array into at most count chunks. /// @@ -628,7 +628,7 @@ module Array = /// Throws ArgumentException /// [] - val splitInto: count: int -> array: 'T[] -> 'T[][] + val splitInto: count: int -> array: 'T array -> 'T array array /// Returns an empty array of the given type. /// The empty array. @@ -640,7 +640,7 @@ module Array = /// [] [] - val empty<'T> : 'T[] + val empty<'T> : 'T array /// Returns the only element of the array. /// @@ -671,14 +671,14 @@ module Array = /// /// /// - /// let inputs: int[] = [| |] + /// let inputs: int array = [| |] /// /// inputs |> Array.exactlyOne /// /// Throws ArgumentException /// [] - val exactlyOne: array: 'T[] -> 'T + val exactlyOne: array: 'T array -> 'T /// Returns the only element of the array or None if array is empty or contains more than one element. /// @@ -708,14 +708,14 @@ module Array = /// /// /// - /// let inputs: int[] = [| |] + /// let inputs: int array = [| |] /// /// inputs |> Array.tryExactlyOne /// /// Evaluates to None /// [] - val tryExactlyOne: array: 'T[] -> 'T option + val tryExactlyOne: array: 'T array -> 'T option /// Returns a new list with the distinct elements of the input array which do not appear in the itemsToExclude sequence, /// using generic hash and equality comparisons to compare values. @@ -738,7 +738,7 @@ module Array = /// Evaluates to [| 2; 4 |] /// [] - val except: itemsToExclude: seq<'T> -> array: 'T[] -> 'T[] when 'T: equality + val except: itemsToExclude: seq<'T> -> array: 'T array -> 'T array when 'T: equality /// Tests if any element of the array satisfies the given predicate. /// @@ -771,7 +771,7 @@ module Array = /// Evaluates to false /// [] - val inline exists: predicate: ('T -> bool) -> array: 'T[] -> bool + val inline exists: predicate: ('T -> bool) -> array: 'T array -> bool /// Tests if any pair of corresponding elements of the arrays satisfies the given predicate. /// @@ -810,7 +810,7 @@ module Array = /// Evaluates to true /// [] - val exists2: predicate: ('T1 -> 'T2 -> bool) -> array1: 'T1[] -> array2: 'T2[] -> bool + val exists2: predicate: ('T1 -> 'T2 -> bool) -> array1: 'T1 array -> array2: 'T2 array -> bool /// Returns a new collection containing only the elements of the collection /// for which the given predicate returns "true". @@ -831,7 +831,7 @@ module Array = /// Evaluates to [| 2; 4 |] /// [] - val filter: predicate: ('T -> bool) -> array: 'T[] -> 'T[] + val filter: predicate: ('T -> bool) -> array: 'T array -> 'T array /// Returns the first element for which the given function returns 'true'. /// Raise if no such element exists. @@ -863,7 +863,7 @@ module Array = /// Throws KeyNotFoundException /// [] - val find: predicate: ('T -> bool) -> array: 'T[] -> 'T + val find: predicate: ('T -> bool) -> array: 'T array -> 'T /// Returns the last element for which the given function returns 'true'. /// Raise if no such element exists. @@ -895,7 +895,7 @@ module Array = /// Throws KeyNotFoundException /// [] - val findBack: predicate: ('T -> bool) -> array: 'T[] -> 'T + val findBack: predicate: ('T -> bool) -> array: 'T array -> 'T /// Returns the index of the first element in the array /// that satisfies the given predicate. Raise if @@ -927,7 +927,7 @@ module Array = /// Throws KeyNotFoundException /// [] - val findIndex: predicate: ('T -> bool) -> array: 'T[] -> int + val findIndex: predicate: ('T -> bool) -> array: 'T array -> int /// Returns the index of the last element in the array /// that satisfies the given predicate. Raise if @@ -960,7 +960,7 @@ module Array = /// Throws KeyNotFoundException /// [] - val findIndexBack: predicate: ('T -> bool) -> array: 'T[] -> int + val findIndexBack: predicate: ('T -> bool) -> array: 'T array -> int /// Tests if all elements of the array satisfy the given predicate. /// @@ -985,7 +985,7 @@ module Array = /// /// [] - val forall: predicate: ('T -> bool) -> array: 'T[] -> bool + val forall: predicate: ('T -> bool) -> array: 'T array -> bool /// Tests if all corresponding elements of the array satisfy the given predicate pairwise. /// @@ -1034,7 +1034,7 @@ module Array = /// Throws ArgumentException. /// [] - val forall2: predicate: ('T1 -> 'T2 -> bool) -> array1: 'T1[] -> array2: 'T2[] -> bool + val forall2: predicate: ('T1 -> 'T2 -> bool) -> array1: 'T1 array -> array2: 'T2 array -> bool /// Applies a function to each element of the collection, threading an accumulator argument /// through the computation. If the input function is f and the elements are i0...iN then computes @@ -1064,7 +1064,7 @@ module Array = /// Evaluates to 2 /// [] - val fold<'T, 'State> : folder: ('State -> 'T -> 'State) -> state: 'State -> array: 'T[] -> 'State + val fold<'T, 'State> : folder: ('State -> 'T -> 'State) -> state: 'State -> array: 'T array -> 'State /// Applies a function to each element of the array, starting from the end, threading an accumulator argument /// through the computation. If the input function is f and the elements are i0...iN then computes @@ -1107,7 +1107,7 @@ module Array = /// /// [] - val foldBack<'T, 'State> : folder: ('T -> 'State -> 'State) -> array: 'T[] -> state: 'State -> 'State + val foldBack<'T, 'State> : folder: ('T -> 'State -> 'State) -> array: 'T array -> state: 'State -> 'State /// Applies a function to pairs of elements drawn from the two collections, /// left-to-right, threading an accumulator argument @@ -1142,7 +1142,7 @@ module Array = /// [] val fold2<'T1, 'T2, 'State> : - folder: ('State -> 'T1 -> 'T2 -> 'State) -> state: 'State -> array1: 'T1[] -> array2: 'T2[] -> 'State + folder: ('State -> 'T1 -> 'T2 -> 'State) -> state: 'State -> array1: 'T1 array -> array2: 'T2 array -> 'State /// Apply a function to pairs of elements drawn from the two collections, right-to-left, /// threading an accumulator argument through the computation. The two input @@ -1191,7 +1191,7 @@ module Array = /// [] val foldBack2<'T1, 'T2, 'State> : - folder: ('T1 -> 'T2 -> 'State -> 'State) -> array1: 'T1[] -> array2: 'T2[] -> state: 'State -> 'State + folder: ('T1 -> 'T2 -> 'State -> 'State) -> array1: 'T1 array -> array2: 'T2 array -> state: 'State -> 'State /// Gets an element from an array. /// @@ -1223,7 +1223,7 @@ module Array = /// Throws IndexOutOfRangeException /// [] - val get: array: 'T[] -> index: int -> 'T + val get: array: 'T array -> index: int -> 'T /// Returns the first element of the array. /// @@ -1250,7 +1250,7 @@ module Array = /// Throws ArgumentException /// [] - val head: array: 'T[] -> 'T + val head: array: 'T array -> 'T /// Applies a key-generating function to each element of an array and yields an array of /// unique keys. Each unique key contains an array of all elements that match @@ -1272,7 +1272,7 @@ module Array = /// Evaluates to [| (1, [| 1; 3; 5 |]); (0, [| 2; 4 |]) |] /// [] - val groupBy: projection: ('T -> 'Key) -> array: 'T[] -> ('Key * 'T[])[] when 'Key: equality + val groupBy: projection: ('T -> 'Key) -> array: 'T array -> ('Key * 'T array) array when 'Key: equality /// Builds a new array whose elements are the corresponding elements of the input array /// paired with the integer index (from 0) of each element. @@ -1292,7 +1292,7 @@ module Array = /// Evaluates to [| (0, "a"); (1, "b"); (2, "c") |] /// [] - val indexed: array: 'T[] -> (int * 'T)[] + val indexed: array: 'T array -> (int * 'T) array /// Creates an array given the dimension and a generator function to compute the elements. /// @@ -1317,7 +1317,7 @@ module Array = /// Throws ArgumentException /// [] - val inline init: count: int -> initializer: (int -> 'T) -> 'T[] + val inline init: count: int -> initializer: (int -> 'T) -> 'T array /// Creates an array where the entries are initially the default value Unchecked.defaultof<'T>. /// @@ -1329,12 +1329,12 @@ module Array = /// /// /// - /// let arr : int[] = Array.zeroCreate 4 + /// let arr : int array = Array.zeroCreate 4 /// /// Evaluates to [| 0; 0; 0; 0 |] /// [] - val zeroCreate: count: int -> 'T[] + val zeroCreate: count: int -> 'T array /// Returns true if the given array is empty, otherwise false. /// @@ -1358,7 +1358,7 @@ module Array = /// Evaluates to false /// [] - val isEmpty: array: 'T[] -> bool + val isEmpty: array: 'T array -> bool /// Applies the given function to each element of the array. /// @@ -1382,7 +1382,7 @@ module Array = /// in the console. /// [] - val inline iter: action: ('T -> unit) -> array: 'T[] -> unit + val inline iter: action: ('T -> unit) -> array: 'T array -> unit /// Applies the given function to pair of elements drawn from matching indices in two arrays. The /// two arrays must have the same lengths, otherwise an ArgumentException is @@ -1411,7 +1411,7 @@ module Array = /// in the console. /// [] - val iter2: action: ('T1 -> 'T2 -> unit) -> array1: 'T1[] -> array2: 'T2[] -> unit + val iter2: action: ('T1 -> 'T2 -> unit) -> array1: 'T1 array -> array2: 'T2 array -> unit /// Applies the given function to each element of the array. The integer passed to the /// function indicates the index of element. @@ -1436,7 +1436,7 @@ module Array = /// in the console. /// [] - val iteri: action: (int -> 'T -> unit) -> array: 'T[] -> unit + val iteri: action: (int -> 'T -> unit) -> array: 'T array -> unit /// Applies the given function to pair of elements drawn from matching indices in two arrays, /// also passing the index of the elements. The two arrays must have the same lengths, @@ -1465,7 +1465,7 @@ module Array = /// in the console. /// [] - val iteri2: action: (int -> 'T1 -> 'T2 -> unit) -> array1: 'T1[] -> array2: 'T2[] -> unit + val iteri2: action: (int -> 'T1 -> 'T2 -> unit) -> array1: 'T1 array -> array2: 'T2 array -> unit /// Returns the last element of the array. /// @@ -1490,7 +1490,7 @@ module Array = /// Throws ArgumentException /// [] - val inline last: array: 'T[] -> 'T + val inline last: array: 'T array -> 'T /// Gets an element from an array. /// @@ -1522,7 +1522,7 @@ module Array = /// Throws ArgumentException /// [] - val item: index: int -> array: 'T[] -> 'T + val item: index: int -> array: 'T array -> 'T /// Returns the length of an array. You can also use property arr.Length. /// @@ -1543,7 +1543,7 @@ module Array = /// Evaluates to 3 /// [] - val length: array: 'T[] -> int + val length: array: 'T array -> int /// Returns the last element of the array. /// Return None if no such element exists. @@ -1568,7 +1568,7 @@ module Array = /// Evaluates to None /// [] - val tryLast: array: 'T[] -> 'T option + val tryLast: array: 'T array -> 'T option /// Builds a new array whose elements are the results of applying the given function /// to each of the elements of the array. @@ -1589,7 +1589,7 @@ module Array = /// Evaluates to [| 1; 3; 2 |] /// [] - val inline map: mapping: ('T -> 'U) -> array: 'T[] -> 'U[] + val inline map: mapping: ('T -> 'U) -> array: 'T array -> 'U array /// Builds a new collection whose elements are the results of applying the given function /// to the corresponding elements of the two collections pairwise. The two input @@ -1615,7 +1615,7 @@ module Array = /// Evaluates to [| 'a'; 'd'; 'o' |] /// [] - val map2: mapping: ('T1 -> 'T2 -> 'U) -> array1: 'T1[] -> array2: 'T2[] -> 'U[] + val map2: mapping: ('T1 -> 'T2 -> 'U) -> array1: 'T1 array -> array2: 'T2 array -> 'U array /// Combines map and fold. Builds a new array whose elements are the results of applying the given function /// to each of the elements of the input array. The function is also used to accumulate a final value. @@ -1646,7 +1646,7 @@ module Array = /// [] val mapFold<'T, 'State, 'Result> : - mapping: ('State -> 'T -> 'Result * 'State) -> state: 'State -> array: 'T[] -> 'Result[] * 'State + mapping: ('State -> 'T -> 'Result * 'State) -> state: 'State -> array: 'T array -> 'Result array * 'State /// Combines map and foldBack. Builds a new array whose elements are the results of applying the given function /// to each of the elements of the input array. The function is also used to accumulate a final value. @@ -1677,7 +1677,7 @@ module Array = /// [] val mapFoldBack<'T, 'State, 'Result> : - mapping: ('T -> 'State -> 'Result * 'State) -> array: 'T[] -> state: 'State -> 'Result[] * 'State + mapping: ('T -> 'State -> 'Result * 'State) -> array: 'T array -> state: 'State -> 'Result array * 'State /// Builds a new collection whose elements are the results of applying the given function /// to the corresponding triples from the three collections. The three input @@ -1706,7 +1706,8 @@ module Array = /// /// [] - val map3: mapping: ('T1 -> 'T2 -> 'T3 -> 'U) -> array1: 'T1[] -> array2: 'T2[] -> array3: 'T3[] -> 'U[] + val map3: + mapping: ('T1 -> 'T2 -> 'T3 -> 'U) -> array1: 'T1 array -> array2: 'T2 array -> array3: 'T3 array -> 'U array /// Builds a new collection whose elements are the results of applying the given function /// to the corresponding elements of the two collections pairwise, also passing the index of @@ -1732,7 +1733,7 @@ module Array = /// Evaluates to [|(0, 'a'); (1, 'd'); (2, 'o')|] /// [] - val mapi2: mapping: (int -> 'T1 -> 'T2 -> 'U) -> array1: 'T1[] -> array2: 'T2[] -> 'U[] + val mapi2: mapping: (int -> 'T1 -> 'T2 -> 'U) -> array1: 'T1 array -> array2: 'T2 array -> 'U array /// Builds a new array whose elements are the results of applying the given function /// to each of the elements of the array. The integer index passed to the @@ -1754,7 +1755,7 @@ module Array = /// Evaluates to [| 10; 11; 12 |] /// [] - val mapi: mapping: (int -> 'T -> 'U) -> array: 'T[] -> 'U[] + val mapi: mapping: (int -> 'T -> 'U) -> array: 'T array -> 'U array /// Returns the greatest of all elements of the array, compared via Operators.max on the function result. /// @@ -1778,14 +1779,14 @@ module Array = /// /// /// - /// let inputs: int[]= [| |] + /// let inputs: int array= [| |] /// /// inputs |> Array.max /// /// Throws System.ArgumentException. /// [] - val inline max: array: 'T[] -> 'T when 'T: comparison + val inline max: array: 'T array -> 'T when 'T: comparison /// Returns the greatest of all elements of the array, compared via Operators.max on the function result. /// @@ -1810,14 +1811,14 @@ module Array = /// /// /// - /// let inputs: string[]= [| |] + /// let inputs: string array= [| |] /// /// inputs |> Array.maxBy (fun s -> s.Length) /// /// Throws System.ArgumentException. /// [] - val inline maxBy: projection: ('T -> 'U) -> array: 'T[] -> 'T when 'U: comparison + val inline maxBy: projection: ('T -> 'U) -> array: 'T array -> 'T when 'U: comparison /// Returns the lowest of all elements of the array, compared via Operators.min. /// @@ -1841,14 +1842,14 @@ module Array = /// /// /// - /// let inputs: int[]= [| |] + /// let inputs: int array= [| |] /// /// inputs |> Array.min /// /// Throws System.ArgumentException. /// [] - val inline min: array: 'T[] -> 'T when 'T: comparison + val inline min: array: 'T array -> 'T when 'T: comparison /// Returns the lowest of all elements of the array, compared via Operators.min on the function result. /// @@ -1873,14 +1874,14 @@ module Array = /// /// /// - /// let inputs: string[]= [| |] + /// let inputs: string array= [| |] /// /// inputs |> Array.minBy (fun s -> s.Length) /// /// Throws System.ArgumentException. /// [] - val inline minBy: projection: ('T -> 'U) -> array: 'T[] -> 'T when 'U: comparison + val inline minBy: projection: ('T -> 'U) -> array: 'T array -> 'T when 'U: comparison /// Builds an array from the given list. /// @@ -1897,7 +1898,7 @@ module Array = /// Evaluates to [| 1; 2; 5 |]. /// [] - val ofList: list: 'T list -> 'T[] + val ofList: list: 'T list -> 'T array /// Builds a new array from the given enumerable object. /// @@ -1916,7 +1917,7 @@ module Array = /// Evaluates to [| 1; 2; 5 |]. /// [] - val ofSeq: source: seq<'T> -> 'T[] + val ofSeq: source: seq<'T> -> 'T array /// Returns an array of each element in the input array and its predecessor, with the /// exception of the first element which is only returned as the predecessor of the second element. @@ -1936,7 +1937,7 @@ module Array = /// Evaluates to [|(1, 2); (2, 3); (3, 4)|]. /// [] - val pairwise: array: 'T[] -> ('T * 'T)[] + val pairwise: array: 'T array -> ('T * 'T) array /// Splits the collection into two collections, containing the /// elements for which the given predicate returns "true" and "false" @@ -1959,7 +1960,7 @@ module Array = /// Evaluates to ([|2; 4|], [|1; 3|]). /// [] - val partition: predicate: ('T -> bool) -> array: 'T[] -> 'T[] * 'T[] + val partition: predicate: ('T -> bool) -> array: 'T array -> 'T array * 'T array /// Returns an array with all elements permuted according to the /// specified permutation. @@ -1981,7 +1982,7 @@ module Array = /// Evaluates to [|4; 1; 2; 3|]. /// [] - val permute: indexMap: (int -> int) -> array: 'T[] -> 'T[] + val permute: indexMap: (int -> int) -> array: 'T array -> 'T array /// Applies a function to each element of the array, threading an accumulator argument /// through the computation. If the input function is f and the elements are i0...iN @@ -2005,7 +2006,7 @@ module Array = /// Evaluates to 1342, by computing ((1 * 10 + 3) * 10 + 4) * 10 + 2 /// [] - val reduce: reduction: ('T -> 'T -> 'T) -> array: 'T[] -> 'T + val reduce: reduction: ('T -> 'T -> 'T) -> array: 'T array -> 'T /// Applies a function to each element of the array, starting from the end, threading an accumulator argument /// through the computation. If the input function is f and the elements are i0...iN @@ -2029,7 +2030,7 @@ module Array = /// Evaluates to 2431, by computing 1 + (3 + (4 + 2 * 10) * 10) * 10 /// [] - val reduceBack: reduction: ('T -> 'T -> 'T) -> array: 'T[] -> 'T + val reduceBack: reduction: ('T -> 'T -> 'T) -> array: 'T array -> 'T /// Creates an array by replicating the given initial value. /// @@ -2047,7 +2048,7 @@ module Array = /// Evaluates to [| "a"; "a"; "a" |]. /// [] - val replicate: count: int -> initial: 'T -> 'T[] + val replicate: count: int -> initial: 'T -> 'T array /// Returns a new array with the elements in reverse order. /// @@ -2064,7 +2065,7 @@ module Array = /// Evaluates to [| 2; 1; 0 |]. /// [] - val rev: array: 'T[] -> 'T[] + val rev: array: 'T array -> 'T array /// Like fold, but return the intermediary and final results. /// @@ -2093,7 +2094,7 @@ module Array = /// state, 1 the next state, -1 the next state, and 2 the final state. /// [] - val scan<'T, 'State> : folder: ('State -> 'T -> 'State) -> state: 'State -> array: 'T[] -> 'State[] + val scan<'T, 'State> : folder: ('State -> 'T -> 'State) -> state: 'State -> array: 'T array -> 'State array /// Like foldBack, but return both the intermediary and final results. /// @@ -2122,7 +2123,7 @@ module Array = /// state, 3 the next state, 1 the next state, and 2 the final state. /// [] - val scanBack<'T, 'State> : folder: ('T -> 'State -> 'State) -> array: 'T[] -> state: 'State -> 'State[] + val scanBack<'T, 'State> : folder: ('T -> 'State -> 'State) -> array: 'T array -> state: 'State -> 'State array /// Returns an array that contains one item only. /// @@ -2137,7 +2138,7 @@ module Array = /// Evaluates to [| 7 |]. /// [] - val inline singleton: value: 'T -> 'T[] + val inline singleton: value: 'T -> 'T array /// Sets an element of an array. /// @@ -2166,7 +2167,7 @@ module Array = /// Throws IndexOutOfRangeException /// [] - val set: array: 'T[] -> index: int -> value: 'T -> unit + val set: array: 'T array -> index: int -> value: 'T -> unit /// Builds a new array that contains the elements of the given array, excluding the first N elements. /// @@ -2206,7 +2207,7 @@ module Array = /// Evaluates to [| "a"; "b"; "c"; "d" |]. /// [] - val skip: count: int -> array: 'T[] -> 'T[] + val skip: count: int -> array: 'T array -> 'T array /// Bypasses elements in an array while the given predicate returns True, and then returns /// the remaining elements in a new array. @@ -2228,7 +2229,7 @@ module Array = /// /// [] - val skipWhile: predicate: ('T -> bool) -> array: 'T[] -> 'T[] + val skipWhile: predicate: ('T -> bool) -> array: 'T array -> 'T array /// Builds a new array that contains the given subrange specified by /// starting index and length. @@ -2261,7 +2262,7 @@ module Array = /// Evaluates to [| 2; 3; 4 |]. /// [] - val sub: array: 'T[] -> startIndex: int -> count: int -> 'T[] + val sub: array: 'T array -> startIndex: int -> count: int -> 'T array /// Sorts the elements of an array, returning a new array. Elements are compared using . /// @@ -2283,7 +2284,7 @@ module Array = /// Evaluates to [| 1; 1; 3; 4; 6; 8 |]. /// [] - val sort: array: 'T[] -> 'T[] when 'T: comparison + val sort: array: 'T array -> 'T array when 'T: comparison /// Sorts the elements of an array, using the given projection for the keys and returning a new array. /// Elements are compared using . @@ -2307,7 +2308,7 @@ module Array = /// Evaluates to [|"a"; "dd"; "bbb"; "cccc"|]. /// [] - val sortBy: projection: ('T -> 'Key) -> array: 'T[] -> 'T[] when 'Key: comparison + val sortBy: projection: ('T -> 'Key) -> array: 'T array -> 'T array when 'Key: comparison /// Sorts the elements of an array, using the given comparison function as the order, returning a new array. /// @@ -2335,7 +2336,7 @@ module Array = /// Evaluates to [|(0, "aa"); (2, "cc"); (3, "dd"); (1, "bbb")|]. /// [] - val sortWith: comparer: ('T -> 'T -> int) -> array: 'T[] -> 'T[] + val sortWith: comparer: ('T -> 'T -> int) -> array: 'T array -> 'T array /// Sorts the elements of an array by mutating the array in-place, using the given projection for the keys. /// Elements are compared using . @@ -2357,7 +2358,7 @@ module Array = /// After evaluation array contains [|"a"; "dd"; "bbb"; "cccc"|]. /// [] - val sortInPlaceBy: projection: ('T -> 'Key) -> array: 'T[] -> unit when 'Key: comparison + val sortInPlaceBy: projection: ('T -> 'Key) -> array: 'T array -> unit when 'Key: comparison /// Sorts the elements of an array by mutating the array in-place, using the given comparison function as the order. /// @@ -2380,7 +2381,7 @@ module Array = /// After evaluation array contains [|(0, "aa"); (2, "cc"); (3, "dd"); (1, "bbb")|]. /// [] - val sortInPlaceWith: comparer: ('T -> 'T -> int) -> array: 'T[] -> unit + val sortInPlaceWith: comparer: ('T -> 'T -> int) -> array: 'T array -> unit /// Sorts the elements of an array by mutating the array in-place, using the given comparison function. /// Elements are compared using . @@ -2398,7 +2399,7 @@ module Array = /// After evaluation array contains [| 1; 1; 3; 4; 6; 8 |]. /// [] - val sortInPlace: array: 'T[] -> unit when 'T: comparison + val sortInPlace: array: 'T array -> unit when 'T: comparison /// Splits an array into two arrays, at the given index. /// @@ -2420,7 +2421,7 @@ module Array = /// Evaluates front to [|8; 4; 3|] and back to [|1; 6; 1|]. /// [] - val splitAt: index: int -> array: 'T[] -> ('T[] * 'T[]) + val splitAt: index: int -> array: 'T array -> ('T array * 'T array) /// Sorts the elements of an array, in descending order, returning a new array. Elements are compared using . /// @@ -2440,7 +2441,7 @@ module Array = /// Evaluates to [| 8; 6; 4; 3; 1; 1 |]. /// [] - val inline sortDescending: array: 'T[] -> 'T[] when 'T: comparison + val inline sortDescending: array: 'T array -> 'T array when 'T: comparison /// Sorts the elements of an array, in descending order, using the given projection for the keys and returning a new array. /// Elements are compared using . @@ -2462,7 +2463,7 @@ module Array = /// Evaluates to [|"cccc"; "bbb"; "dd"; "a"|]. /// [] - val inline sortByDescending: projection: ('T -> 'Key) -> array: 'T[] -> 'T[] when 'Key: comparison + val inline sortByDescending: projection: ('T -> 'Key) -> array: 'T array -> 'T array when 'Key: comparison /// Returns the sum of the elements in the array. /// @@ -2481,7 +2482,7 @@ module Array = /// Evaluates to 11. /// [] - val inline sum: array: ^T[] -> ^T when ^T: (static member (+): ^T * ^T -> ^T) and ^T: (static member Zero: ^T) + val inline sum: array: ^T array -> ^T when ^T: (static member (+): ^T * ^T -> ^T) and ^T: (static member Zero: ^T) /// Returns the sum of the results generated by applying the function to each element of the array. /// @@ -2502,7 +2503,7 @@ module Array = /// [] val inline sumBy: - projection: ('T -> ^U) -> array: 'T[] -> ^U + projection: ('T -> ^U) -> array: 'T array -> ^U when ^U: (static member (+): ^U * ^U -> ^U) and ^U: (static member Zero: ^U) /// Returns the first N elements of the array. @@ -2547,7 +2548,7 @@ module Array = /// Evaluates to [| |]. /// [] - val take: count: int -> array: 'T[] -> 'T[] + val take: count: int -> array: 'T array -> 'T array /// Returns an array that contains all elements of the original array while the /// given predicate returns True, and then returns no further elements. @@ -2569,7 +2570,7 @@ module Array = /// /// [] - val takeWhile: predicate: ('T -> bool) -> array: 'T[] -> 'T[] + val takeWhile: predicate: ('T -> bool) -> array: 'T array -> 'T array /// Returns a new array containing the elements of the original except the first element. /// @@ -2590,7 +2591,7 @@ module Array = /// /// [] - val tail: array: 'T[] -> 'T[] + val tail: array: 'T array -> 'T array /// Builds a list from the given array. /// @@ -2609,7 +2610,7 @@ module Array = /// Evaluates to [ 1; 2; 5 ]. /// [] - val toList: array: 'T[] -> 'T list + val toList: array: 'T array -> 'T list /// Views the given array as a sequence. /// @@ -2628,7 +2629,7 @@ module Array = /// Evaluates to seq { 1; 2; 5 }. /// [] - val toSeq: array: 'T[] -> seq<'T> + val toSeq: array: 'T array -> seq<'T> /// Returns the transpose of the given sequence of arrays. /// @@ -2650,7 +2651,7 @@ module Array = /// Evaluates to [|[|10; 11|]; [|20; 21|]; [|30; 31|]|]. /// [] - val transpose: arrays: seq<'T[]> -> 'T[][] + val transpose: arrays: seq<'T array> -> 'T array array /// Returns at most N elements in a new array. /// @@ -2688,7 +2689,7 @@ module Array = /// Evaluates to [| |]. /// [] - val truncate: count: int -> array: 'T[] -> 'T[] + val truncate: count: int -> array: 'T array -> 'T array /// Returns the first element for which the given function returns True. /// Return None if no such element exists. @@ -2718,7 +2719,7 @@ module Array = /// Evaluates to None /// [] - val tryFind: predicate: ('T -> bool) -> array: 'T[] -> 'T option + val tryFind: predicate: ('T -> bool) -> array: 'T array -> 'T option /// Returns the last element for which the given function returns True. /// Return None if no such element exists. @@ -2748,7 +2749,7 @@ module Array = /// Evaluates to None /// [] - val tryFindBack: predicate: ('T -> bool) -> array: 'T[] -> 'T option + val tryFindBack: predicate: ('T -> bool) -> array: 'T array -> 'T option /// Returns the index of the first element in the array /// that satisfies the given predicate. @@ -2778,7 +2779,7 @@ module Array = /// Evaluates to None /// [] - val tryFindIndex: predicate: ('T -> bool) -> array: 'T[] -> int option + val tryFindIndex: predicate: ('T -> bool) -> array: 'T array -> int option /// Tries to find the nth element in the array. /// Returns None if index is negative or the input array does not contain enough elements. @@ -2808,7 +2809,7 @@ module Array = /// Evaluates to None. /// [] - val tryItem: index: int -> array: 'T[] -> 'T option + val tryItem: index: int -> array: 'T array -> 'T option /// Returns the index of the last element in the array /// that satisfies the given predicate. @@ -2838,7 +2839,7 @@ module Array = /// Evaluates to None /// [] - val tryFindIndexBack: predicate: ('T -> bool) -> array: 'T[] -> int option + val tryFindIndexBack: predicate: ('T -> bool) -> array: 'T array -> int option /// Returns an array that contains the elements generated by the given computation. /// The generator is repeatedly called to build the list until it returns `None`. @@ -2857,7 +2858,7 @@ module Array = /// Evaluates to [| 1; 2; 4; 8; 16; 32; 64 |] /// [] - val unfold<'T, 'State> : generator: ('State -> ('T * 'State) option) -> state: 'State -> 'T[] + val unfold<'T, 'State> : generator: ('State -> ('T * 'State) option) -> state: 'State -> 'T array /// Splits an array of pairs into two arrays. /// @@ -2876,7 +2877,7 @@ module Array = /// Evaluates numbers to [|1; 2|] and names to [|"one"; "two"|]. /// [] - val unzip: array: ('T1 * 'T2)[] -> ('T1[] * 'T2[]) + val unzip: array: ('T1 * 'T2) array -> ('T1 array * 'T2 array) /// Splits an array of triples into three arrays. /// @@ -2895,7 +2896,7 @@ module Array = /// Evaluates numbers to [|1; 2|], names to [|"one"; "two"|] and roman to [|"I"; "II"|]. /// [] - val unzip3: array: ('T1 * 'T2 * 'T3)[] -> ('T1[] * 'T2[] * 'T3[]) + val unzip3: array: ('T1 * 'T2 * 'T3) array -> ('T1 array * 'T2 array * 'T3 array) /// Returns a new array containing only the elements of the array /// for which the given predicate returns "true". @@ -2918,7 +2919,7 @@ module Array = /// Evaluates to [| 2; 4 |] /// [] - val where: predicate: ('T -> bool) -> array: 'T[] -> 'T[] + val where: predicate: ('T -> bool) -> array: 'T array -> 'T array /// Returns an array of sliding windows containing elements drawn from the input /// array. Each window is returned as a fresh array. @@ -2940,7 +2941,7 @@ module Array = /// Evaluates to [|[|1; 2; 3|]; [|2; 3; 4|]; [|3; 4; 5|]|] /// [] - val windowed: windowSize: int -> array: 'T[] -> 'T[][] + val windowed: windowSize: int -> array: 'T array -> 'T array array /// Combines the two arrays into an array of pairs. The two arrays must have equal lengths, otherwise an ArgumentException is /// raised. @@ -2963,7 +2964,7 @@ module Array = /// Evaluates to [| (1, "one"); (2, "two") |]. /// [] - val zip: array1: 'T1[] -> array2: 'T2[] -> ('T1 * 'T2)[] + val zip: array1: 'T1 array -> array2: 'T2 array -> ('T1 * 'T2) array /// Combines three arrays into an array of pairs. The three arrays must have equal lengths, otherwise an ArgumentException is /// raised. @@ -2988,7 +2989,7 @@ module Array = /// Evaluates to [|(1, "one", "I"); (2, "two", "II")|]. /// [] - val zip3: array1: 'T1[] -> array2: 'T2[] -> array3: 'T3[] -> ('T1 * 'T2 * 'T3)[] + val zip3: array1: 'T1 array -> array2: 'T2 array -> array3: 'T3 array -> ('T1 * 'T2 * 'T3) array /// Return a new array with the item at a given index removed. /// @@ -3008,7 +3009,7 @@ module Array = /// Evaluates to [| 0; 2 |]. /// [] - val removeAt: index: int -> source: 'T[] -> 'T[] + val removeAt: index: int -> source: 'T array -> 'T array /// Return a new array with the number of items starting at a given index removed. /// @@ -3029,7 +3030,7 @@ module Array = /// Evaluates to [| 0; 3 |]. /// [] - val removeManyAt: index: int -> count: int -> source: 'T[] -> 'T[] + val removeManyAt: index: int -> count: int -> source: 'T array -> 'T array /// Return a new array with the item at a given index set to the new value. /// @@ -3050,7 +3051,7 @@ module Array = /// Evaluates to [| 0; 9; 2 |]. /// [] - val updateAt: index: int -> value: 'T -> source: 'T[] -> 'T[] + val updateAt: index: int -> value: 'T -> source: 'T array -> 'T array /// Return a new array with a new item inserted before the given index. /// @@ -3071,7 +3072,7 @@ module Array = /// Evaluates to [| 0; 9; 1; 2 |]. /// [] - val insertAt: index: int -> value: 'T -> source: 'T[] -> 'T[] + val insertAt: index: int -> value: 'T -> source: 'T array -> 'T array /// Return a new array with new items inserted before the given index. /// @@ -3092,7 +3093,7 @@ module Array = /// Evaluates to [| 0; 8; 9; 1; 2 |]. /// [] - val insertManyAt: index: int -> values: seq<'T> -> source: 'T[] -> 'T[] + val insertManyAt: index: int -> values: seq<'T> -> source: 'T array -> 'T array /// Provides parallel operations on arrays module Parallel = @@ -3121,7 +3122,7 @@ module Array = /// [] [] - val forall: predicate: ('T -> bool) -> array: 'T[] -> bool + val forall: predicate: ('T -> bool) -> array: 'T array -> bool /// Tests if any element of the array satisfies the given predicate. /// @@ -3155,7 +3156,7 @@ module Array = /// [] [] - val exists: predicate: ('T -> bool) -> array: 'T[] -> bool + val exists: predicate: ('T -> bool) -> array: 'T array -> bool /// Returns the first element for which the given function returns True. /// Returns None if no such element exists. @@ -3186,7 +3187,7 @@ module Array = /// [] [] - val tryFind: predicate: ('T -> bool) -> array: 'T[] -> 'T option + val tryFind: predicate: ('T -> bool) -> array: 'T array -> 'T option /// Returns the index of the first element in the array /// that satisfies the given predicate. @@ -3217,7 +3218,7 @@ module Array = /// [] [] - val tryFindIndex: predicate: ('T -> bool) -> array: 'T[] -> int option + val tryFindIndex: predicate: ('T -> bool) -> array: 'T array -> int option /// Applies the given function to successive elements, returning the first /// result where the function returns Some(x) for some x. If the function @@ -3250,7 +3251,7 @@ module Array = /// [] [] - val tryPick: chooser: ('T -> 'U option) -> array: 'T[] -> 'U option + val tryPick: chooser: ('T -> 'U option) -> array: 'T array -> 'U option /// Applies a function to each element of the array in parallel, threading an accumulator argument /// through the computation for each thread involved in the computation. After processing entire input, results from all threads are reduced together. @@ -3278,7 +3279,7 @@ module Array = [] [] - val inline reduce: reduction: ('T -> 'T -> 'T) -> array: 'T[] -> 'T + val inline reduce: reduction: ('T -> 'T -> 'T) -> array: 'T array -> 'T /// Applies a projection function to each element of the array in parallel, reducing elements in each thread with a dedicated 'reduction' function. /// After processing entire input, results from all threads are reduced together. @@ -3306,7 +3307,7 @@ module Array = [] [] - val reduceBy: projection: ('T -> 'U) -> reduction: ('U -> 'U -> 'U) -> array: 'T[] -> 'U + val reduceBy: projection: ('T -> 'U) -> reduction: ('U -> 'U -> 'U) -> array: 'T array -> 'U /// Returns the greatest of all elements of the array, compared via Operators.max. /// @@ -3330,7 +3331,7 @@ module Array = /// /// /// - /// let inputs: int[]= [| |] + /// let inputs: int array= [| |] /// /// inputs |> Array.Parallel.max /// @@ -3338,7 +3339,7 @@ module Array = /// [] [] - val inline max: array: 'T[] -> 'T when 'T: comparison + val inline max: array: 'T array -> 'T when 'T: comparison /// Returns the greatest of all elements of the array, compared via Operators.max on the function result. /// @@ -3363,7 +3364,7 @@ module Array = /// /// /// - /// let inputs: string[]= [| |] + /// let inputs: string array= [| |] /// /// inputs |> Array.Parallel.maxBy (fun s -> s.Length) /// @@ -3371,7 +3372,7 @@ module Array = /// [] [] - val inline maxBy: projection: ('T -> 'U) -> array: 'T[] -> 'T when 'U: comparison + val inline maxBy: projection: ('T -> 'U) -> array: 'T array -> 'T when 'U: comparison /// Returns the smallest of all elements of the array, compared via Operators.min. /// @@ -3395,7 +3396,7 @@ module Array = /// /// /// - /// let inputs: int[]= [| |] + /// let inputs: int array= [| |] /// /// inputs |> Array.Parallel.min /// @@ -3403,7 +3404,7 @@ module Array = /// [] [] - val inline min: array: 'T[] -> 'T when 'T: comparison + val inline min: array: 'T array -> 'T when 'T: comparison /// Returns the lowest of all elements of the array, compared via Operators.min on the function result. /// @@ -3428,7 +3429,7 @@ module Array = /// /// /// - /// let inputs: string[]= [| |] + /// let inputs: string array= [| |] /// /// inputs |> Array.Parallel.minBy (fun s -> s.Length) /// @@ -3436,7 +3437,7 @@ module Array = /// [] [] - val inline minBy: projection: ('T -> 'U) -> array: 'T[] -> 'T when 'U: comparison + val inline minBy: projection: ('T -> 'U) -> array: 'T array -> 'T when 'U: comparison /// Returns the sum of the elements in the array. /// @@ -3456,7 +3457,8 @@ module Array = /// [] [] - val inline sum: array: ^T[] -> ^T when ^T: (static member (+): ^T * ^T -> ^T) and ^T: (static member Zero: ^T) + val inline sum: + array: ^T array -> ^T when ^T: (static member (+): ^T * ^T -> ^T) and ^T: (static member Zero: ^T) /// Returns the sum of the results generated by applying the function to each element of the array. /// @@ -3478,7 +3480,7 @@ module Array = [] [] val inline sumBy: - projection: ('T -> ^U) -> array: 'T[] -> ^U + projection: ('T -> ^U) -> array: 'T array -> ^U when ^U: (static member (+): ^U * ^U -> ^U) and ^U: (static member Zero: ^U) /// Returns the average of the elements in the array. @@ -3506,7 +3508,7 @@ module Array = [] [] val inline average: - array: ^T[] -> ^T + array: ^T array -> ^T when ^T: (static member (+): ^T * ^T -> ^T) and ^T: (static member DivideByInt: ^T * int -> ^T) /// Returns the average of the elements generated by applying the function to each element of the array. @@ -3535,7 +3537,7 @@ module Array = /// /// type Foo = { Bar: float } /// - /// let input : Foo[] = [| |] + /// let input : Foo array = [| |] /// /// input |> Array.Parallel.averageBy (fun foo -> foo.Bar) /// @@ -3544,7 +3546,7 @@ module Array = [] [] val inline averageBy: - projection: ('T -> ^U) -> array: 'T[] -> ^U + projection: ('T -> ^U) -> array: 'T array -> ^U when ^U: (static member (+): ^U * ^U -> ^U) and ^U: (static member DivideByInt: ^U * int -> ^U) /// Apply the given function to each element of the array. Return @@ -3579,7 +3581,7 @@ module Array = /// Evaluates to [| 2 |] /// [] - val choose: chooser: ('T -> 'U option) -> array: 'T[] -> 'U[] + val choose: chooser: ('T -> 'U option) -> array: 'T array -> 'U array /// For each element of the array, apply the given function. Concatenate all the results and return the combined array. /// @@ -3589,13 +3591,13 @@ module Array = /// /// The input array. /// - /// 'U[] + /// 'U array /// /// Thrown when the input array is null. /// /// /// - /// type Foo = { Bar: int[] } + /// type Foo = { Bar: int array } /// /// let input = [| {Bar = [| 1; 2 |]}; {Bar = [| 3; 4 |]} |] /// @@ -3613,7 +3615,7 @@ module Array = /// Evaluates to [| 1; 2; 3; 4 |] /// [] - val collect: mapping: ('T -> 'U[]) -> array: 'T[] -> 'U[] + val collect: mapping: ('T -> 'U array) -> array: 'T array -> 'U array /// Build a new array whose elements are the results of applying the given function /// to each of the elements of the array. @@ -3637,7 +3639,7 @@ module Array = /// Evaluates to [| 1; 3; 2 |] /// [] - val map: mapping: ('T -> 'U) -> array: 'T[] -> 'U[] + val map: mapping: ('T -> 'U) -> array: 'T array -> 'U array /// Build a new array whose elements are the results of applying the given function /// to each of the elements of the array. The integer index passed to the @@ -3662,7 +3664,7 @@ module Array = /// Evaluates to [| 10; 11; 12 |] /// [] - val mapi: mapping: (int -> 'T -> 'U) -> array: 'T[] -> 'U[] + val mapi: mapping: (int -> 'T -> 'U) -> array: 'T array -> 'U array /// Applies a key-generating function to each element of an array in parallel and yields an array of /// unique keys. Each unique key contains an array of all elements that match @@ -3689,7 +3691,7 @@ module Array = [] [] - val groupBy: projection: ('T -> 'Key) -> array: 'T[] -> ('Key * 'T[])[] when 'Key: equality + val groupBy: projection: ('T -> 'Key) -> array: 'T array -> ('Key * 'T array) array when 'Key: equality /// Apply the given function to each element of the array. /// @@ -3715,7 +3717,7 @@ module Array = /// /// [] - val iter: action: ('T -> unit) -> array: 'T[] -> unit + val iter: action: ('T -> unit) -> array: 'T array -> unit /// Apply the given function to each element of the array. The integer passed to the /// function indicates the index of element. @@ -3742,7 +3744,7 @@ module Array = /// /// [] - val iteri: action: (int -> 'T -> unit) -> array: 'T[] -> unit + val iteri: action: (int -> 'T -> unit) -> array: 'T array -> unit /// Create an array given the dimension and a generator function to compute the elements. /// @@ -3761,7 +3763,7 @@ module Array = /// Evaluates to [| 5; 6; 7; 8 |] /// [] - val init: count: int -> initializer: (int -> 'T) -> 'T[] + val init: count: int -> initializer: (int -> 'T) -> 'T array /// Split the collection into two collections, containing the /// elements for which the given predicate returns "true" and "false" @@ -3786,7 +3788,7 @@ module Array = /// Evaluates to ([|2; 4|], [|1; 3|]). /// [] - val partition: predicate: ('T -> bool) -> array: 'T[] -> 'T[] * 'T[] + val partition: predicate: ('T -> bool) -> array: 'T array -> 'T array * 'T array /// Sorts the elements of an array in parallel, returning a new array. Elements are compared using . /// @@ -3809,7 +3811,7 @@ module Array = /// [] [] - val sort: array: 'T[] -> 'T[] when 'T: comparison + val sort: array: 'T array -> 'T array when 'T: comparison /// Sorts the elements of an array in parallel, using the given projection for the keys and returning a new array. /// Elements are compared using . @@ -3835,7 +3837,7 @@ module Array = [] [] - val sortBy: projection: ('T -> 'Key) -> array: 'T[] -> 'T[] when 'Key: comparison + val sortBy: projection: ('T -> 'Key) -> array: 'T array -> 'T array when 'Key: comparison /// Sorts the elements of an array in parallel, using the given comparison function as the order, returning a new array. /// @@ -3864,7 +3866,7 @@ module Array = /// [] [] - val sortWith: comparer: ('T -> 'T -> int) -> array: 'T[] -> 'T[] + val sortWith: comparer: ('T -> 'T -> int) -> array: 'T array -> 'T array /// Sorts the elements of an array by mutating the array in-place in parallel, using the given projection for the keys. /// Elements are compared using . @@ -3887,7 +3889,7 @@ module Array = /// [] [] - val sortInPlaceBy: projection: ('T -> 'Key) -> array: 'T[] -> unit when 'Key: comparison + val sortInPlaceBy: projection: ('T -> 'Key) -> array: 'T array -> unit when 'Key: comparison /// Sorts the elements of an array by mutating the array in-place in parallel, using the given comparison function as the order. /// @@ -3911,7 +3913,7 @@ module Array = /// [] [] - val sortInPlaceWith: comparer: ('T -> 'T -> int) -> array: 'T[] -> unit + val sortInPlaceWith: comparer: ('T -> 'T -> int) -> array: 'T array -> unit /// Sorts the elements of an array by mutating the array in-place in parallel, using the given comparison function. /// Elements are compared using . @@ -3930,7 +3932,7 @@ module Array = /// [] [] - val sortInPlace: array: 'T[] -> unit when 'T: comparison + val sortInPlace: array: 'T array -> unit when 'T: comparison /// Sorts the elements of an array in parallel, in descending order, returning a new array. Elements are compared using . /// @@ -3951,7 +3953,7 @@ module Array = /// [] [] - val sortDescending: array: 'T[] -> 'T[] when 'T: comparison + val sortDescending: array: 'T array -> 'T array when 'T: comparison /// Sorts the elements of an array in parallel, in descending order, using the given projection for the keys and returning a new array. /// Elements are compared using . @@ -3974,7 +3976,7 @@ module Array = /// [] [] - val sortByDescending: projection: ('T -> 'Key) -> array: 'T[] -> 'T[] when 'Key: comparison + val sortByDescending: projection: ('T -> 'Key) -> array: 'T array -> 'T array when 'Key: comparison /// Combines the two arrays into an array of pairs. The two arrays must have equal lengths, otherwise an ArgumentException is /// raised. @@ -3998,7 +4000,7 @@ module Array = /// [] [] - val zip: array1: 'T1[] -> array2: 'T2[] -> ('T1 * 'T2)[] + val zip: array1: 'T1 array -> array2: 'T2 array -> ('T1 * 'T2) array /// Returns a new collection containing only the elements of the collection /// for which the given predicate returns true. @@ -4020,4 +4022,4 @@ module Array = /// [] [] - val filter: predicate: ('T -> bool) -> array: 'T[] -> 'T[] + val filter: predicate: ('T -> bool) -> array: 'T array -> 'T array diff --git a/src/FSharp.Core/async.fs b/src/FSharp.Core/async.fs index 7eedb9e167c..b530fa72485 100644 --- a/src/FSharp.Core/async.fs +++ b/src/FSharp.Core/async.fs @@ -2253,7 +2253,7 @@ module CommonExtensions = type System.IO.Stream with [] // give the extension member a 'nice', unmangled compiled name, unique within this module - member stream.AsyncRead(buffer: byte[], ?offset, ?count) = + member stream.AsyncRead(buffer: byte array, ?offset, ?count) = let offset = defaultArg offset 0 let count = defaultArg count buffer.Length Async.FromBeginEnd(buffer, offset, count, stream.BeginRead, stream.EndRead) @@ -2275,7 +2275,7 @@ module CommonExtensions = } [] // give the extension member a 'nice', unmangled compiled name, unique within this module - member stream.AsyncWrite(buffer: byte[], ?offset: int, ?count: int) = + member stream.AsyncWrite(buffer: byte array, ?offset: int, ?count: int) = let offset = defaultArg offset 0 let count = defaultArg count buffer.Length Async.FromBeginEnd(buffer, offset, count, stream.BeginWrite, stream.EndWrite) @@ -2365,7 +2365,7 @@ module WebExtensions = ) [] // give the extension member a 'nice', unmangled compiled name, unique within this module - member this.AsyncDownloadData(address: Uri) : Async = + member this.AsyncDownloadData(address: Uri) : Async = this.Download( event = this.DownloadDataCompleted, handler = (fun action -> Net.DownloadDataCompletedEventHandler action), diff --git a/src/FSharp.Core/async.fsi b/src/FSharp.Core/async.fsi index 35b3e227a5d..6b621176c9d 100644 --- a/src/FSharp.Core/async.fsi +++ b/src/FSharp.Core/async.fsi @@ -428,7 +428,7 @@ namespace Microsoft.FSharp.Control /// /// This will print "3", "5", "7", "11" (in any order) in 1-2 seconds and then [| false; true; true; true; false; true |]. /// - static member Parallel : computations:seq> -> Async<'T[]> + static member Parallel : computations:seq> -> Async<'T array> /// Creates an asynchronous computation that executes all the given asynchronous computations, /// initially queueing each as work items and using a fork/join pattern. @@ -475,7 +475,7 @@ namespace Microsoft.FSharp.Control /// This will print "3", "5" (in any order) in 1-2 seconds, and then "7", "11" (in any order) in 1-2 more seconds and then /// [| false; true; true; true; false; true |]. /// - static member Parallel : computations:seq> * ?maxDegreeOfParallelism : int -> Async<'T[]> + static member Parallel : computations:seq> * ?maxDegreeOfParallelism : int -> Async<'T array> /// Creates an asynchronous computation that executes all the given asynchronous computations sequentially. /// @@ -520,7 +520,7 @@ namespace Microsoft.FSharp.Control /// This will print "3", "5", "7", "11" with ~1-2 seconds between them except for pauses where even numbers would be and then /// prints [| false; true; true; true; false; true |]. /// - static member Sequential : computations:seq> -> Async<'T[]> + static member Sequential : computations:seq> -> Async<'T array> /// /// Creates an asynchronous computation that executes all given asynchronous computations in parallel, @@ -1409,17 +1409,17 @@ namespace Microsoft.FSharp.Control /// /// [] // give the extension member a nice, unmangled compiled name, unique within this module - member AsyncRead : buffer:byte[] * ?offset:int * ?count:int -> Async + member AsyncRead : buffer:byte array * ?offset:int * ?count:int -> Async /// Returns an asynchronous computation that will read the given number of bytes from the stream. /// /// The number of bytes to read. /// - /// An asynchronous computation that returns the read byte[] when run. + /// An asynchronous computation that returns the read byte array when run. /// /// [] // give the extension member a nice, unmangled compiled name, unique within this module - member AsyncRead : count:int -> Async + member AsyncRead : count:int -> Async /// Returns an asynchronous computation that will write the given bytes to the stream. /// @@ -1435,7 +1435,7 @@ namespace Microsoft.FSharp.Control /// /// [] // give the extension member a nice, unmangled compiled name, unique within this module - member AsyncWrite : buffer:byte[] * ?offset:int * ?count:int -> Async + member AsyncWrite : buffer:byte array * ?offset:int * ?count:int -> Async ///The family of first class event values for delegate types that satisfy the F# delegate constraint. @@ -1522,7 +1522,7 @@ namespace Microsoft.FSharp.Control /// /// Downloads the data in bytes and decodes it to a string. [] // give the extension member a nice, unmangled compiled name, unique within this module - member AsyncDownloadData : address:System.Uri -> Async + member AsyncDownloadData : address:System.Uri -> Async /// Returns an asynchronous computation that, when run, will wait for the download of the given URI to specified file. /// diff --git a/src/FSharp.Core/collections.fsi b/src/FSharp.Core/collections.fsi index 1e8494aa9e3..9baf6097394 100644 --- a/src/FSharp.Core/collections.fsi +++ b/src/FSharp.Core/collections.fsi @@ -70,7 +70,7 @@ module HashIdentity = /// /// open System.Collections.Generic /// - /// let dict = new Dictionary<int[],int>(HashIdentity.Structural) + /// let dict = new Dictionary<int array,int>(HashIdentity.Structural) /// /// let arr1 = [| 1;2;3 |] /// let arr2 = [| 1;2;3 |] @@ -134,7 +134,7 @@ module HashIdentity = /// /// open System.Collections.Generic /// - /// let dict = new Dictionary<int[],int>(HashIdentity.Structural) + /// let dict = new Dictionary<int array,int>(HashIdentity.Structural) /// /// let arr1 = [| 1;2;3 |] /// let arr2 = [| 1;2;3 |] diff --git a/src/FSharp.Core/event.fs b/src/FSharp.Core/event.fs index da356eefb05..338d7275fc3 100644 --- a/src/FSharp.Core/event.fs +++ b/src/FSharp.Core/event.fs @@ -31,7 +31,7 @@ module private Atomic = type DelegateEvent<'Delegate when 'Delegate :> System.Delegate>() = let mutable multicast: System.Delegate = null - member x.Trigger(args: obj[]) = + member x.Trigger(args: obj array) = match multicast with | null -> () | d -> d.DynamicInvoke(args) |> ignore diff --git a/src/FSharp.Core/event.fsi b/src/FSharp.Core/event.fsi index 12557f0dc22..09225b9b0fa 100644 --- a/src/FSharp.Core/event.fsi +++ b/src/FSharp.Core/event.fsi @@ -23,7 +23,7 @@ type DelegateEvent<'Delegate when 'Delegate :> System.Delegate> = /// The parameters for the event. /// /// - member Trigger: args: obj[] -> unit + member Trigger: args: obj array -> unit /// Publishes the event as a first class event value. /// diff --git a/src/FSharp.Core/fslib-extra-pervasives.fs b/src/FSharp.Core/fslib-extra-pervasives.fs index d12a20211b8..def5d42c2e5 100644 --- a/src/FSharp.Core/fslib-extra-pervasives.fs +++ b/src/FSharp.Core/fslib-extra-pervasives.fs @@ -215,7 +215,7 @@ module ExtraTopLevelOperators = let getArray (vals: seq<'T>) = match vals with - | :? ('T[]) as arr -> arr + | :? ('T array) as arr -> arr | _ -> Seq.toArray vals [] @@ -415,7 +415,7 @@ type TypeProviderConfig (systemRuntimeContainsType: string -> bool, getReferencedAssembliesOption: (unit -> string array) option) = let mutable resolutionFolder: string = null let mutable runtimeAssembly: string = null - let mutable referencedAssemblies: string[] = null + let mutable referencedAssemblies: string array = null let mutable temporaryFolder: string = null let mutable isInvalidationSupported: bool = false let mutable useResolutionFolderAtRuntime: bool = false @@ -468,31 +468,31 @@ type IProvidedNamespace = abstract NamespaceName: string - abstract GetNestedNamespaces: unit -> IProvidedNamespace[] + abstract GetNestedNamespaces: unit -> IProvidedNamespace array - abstract GetTypes: unit -> Type[] + abstract GetTypes: unit -> Type array abstract ResolveTypeName: typeName: string -> Type type ITypeProvider = inherit System.IDisposable - abstract GetNamespaces: unit -> IProvidedNamespace[] + abstract GetNamespaces: unit -> IProvidedNamespace array - abstract GetStaticParameters: typeWithoutArguments: Type -> ParameterInfo[] + abstract GetStaticParameters: typeWithoutArguments: Type -> ParameterInfo array abstract ApplyStaticArguments: - typeWithoutArguments: Type * typePathWithArguments: string[] * staticArguments: obj[] -> Type + typeWithoutArguments: Type * typePathWithArguments: string array * staticArguments: obj array -> Type - abstract GetInvokerExpression: syntheticMethodBase: MethodBase * parameters: Expr[] -> Expr + abstract GetInvokerExpression: syntheticMethodBase: MethodBase * parameters: Expr array -> Expr [] abstract Invalidate: IEvent - abstract GetGeneratedAssemblyContents: assembly: System.Reflection.Assembly -> byte[] + abstract GetGeneratedAssemblyContents: assembly: System.Reflection.Assembly -> byte array type ITypeProvider2 = - abstract GetStaticParametersForMethod: methodWithoutArguments: MethodBase -> ParameterInfo[] + abstract GetStaticParametersForMethod: methodWithoutArguments: MethodBase -> ParameterInfo array abstract ApplyStaticArgumentsForMethod: - methodWithoutArguments: MethodBase * methodNameWithArguments: string * staticArguments: obj[] -> MethodBase + methodWithoutArguments: MethodBase * methodNameWithArguments: string * staticArguments: obj array -> MethodBase diff --git a/src/FSharp.Core/fslib-extra-pervasives.fsi b/src/FSharp.Core/fslib-extra-pervasives.fsi index 619f5ff05d4..bd4bf0ee8b5 100644 --- a/src/FSharp.Core/fslib-extra-pervasives.fsi +++ b/src/FSharp.Core/fslib-extra-pervasives.fsi @@ -459,7 +459,7 @@ namespace Microsoft.FSharp.Core.CompilerServices new : systemRuntimeContainsType : (string -> bool) -> TypeProviderConfig /// Create a configuration which calls the given functions for the corresponding operation. - new : systemRuntimeContainsType : (string -> bool) * getReferencedAssemblies : (unit -> string[]) -> TypeProviderConfig + new : systemRuntimeContainsType : (string -> bool) * getReferencedAssemblies : (unit -> string array) -> TypeProviderConfig /// Get the full path to use to resolve relative paths in any file name arguments given to the type provider instance. member ResolutionFolder : string with get,set @@ -468,7 +468,7 @@ namespace Microsoft.FSharp.Core.CompilerServices member RuntimeAssembly : string with get,set /// Get the referenced assemblies for the type provider instance. - member ReferencedAssemblies : string[] with get,set + member ReferencedAssemblies : string array with get,set /// Get the full path to use for temporary files for the type provider instance. member TemporaryFolder : string with get,set @@ -493,13 +493,13 @@ namespace Microsoft.FSharp.Core.CompilerServices abstract NamespaceName : string /// The sub-namespaces in this namespace. An optional member to prevent generation of namespaces until an outer namespace is explored. - abstract GetNestedNamespaces : unit -> IProvidedNamespace[] + abstract GetNestedNamespaces : unit -> IProvidedNamespace array /// /// The top-level types /// /// - abstract GetTypes : unit -> Type[] + abstract GetTypes : unit -> Type array /// /// Compilers call this method to query a type provider for a type name. @@ -518,7 +518,7 @@ namespace Microsoft.FSharp.Core.CompilerServices /// /// Gets the namespaces provided by the type provider. /// - abstract GetNamespaces : unit -> IProvidedNamespace[] + abstract GetNamespaces : unit -> IProvidedNamespace array /// /// Get the static parameters for a provided type. @@ -527,7 +527,7 @@ namespace Microsoft.FSharp.Core.CompilerServices /// A type returned by GetTypes or ResolveTypeName /// /// - abstract GetStaticParameters : typeWithoutArguments:Type -> ParameterInfo[] + abstract GetStaticParameters : typeWithoutArguments:Type -> ParameterInfo array /// /// Apply static arguments to a provided type that accepts static arguments. @@ -540,7 +540,7 @@ namespace Microsoft.FSharp.Core.CompilerServices /// the static parameters, indexed by name /// /// - abstract ApplyStaticArguments : typeWithoutArguments:Type * typePathWithArguments:string[] * staticArguments:obj[] -> Type + abstract ApplyStaticArguments : typeWithoutArguments:Type * typePathWithArguments:string array * staticArguments:obj array -> Type /// /// Called by the compiler to ask for an Expression tree to replace the given MethodBase with. @@ -550,7 +550,7 @@ namespace Microsoft.FSharp.Core.CompilerServices /// Expressions that represent the parameters to this call. /// /// An expression that the compiler will use in place of the given method base. - abstract GetInvokerExpression : syntheticMethodBase:MethodBase * parameters:Expr[] -> Expr + abstract GetInvokerExpression : syntheticMethodBase:MethodBase * parameters:Expr array -> Expr /// /// Triggered when an assumption changes that invalidates the resolutions so far reported by the provider @@ -561,7 +561,7 @@ namespace Microsoft.FSharp.Core.CompilerServices /// /// Get the physical contents of the given logical provided assembly. /// - abstract GetGeneratedAssemblyContents : assembly:Assembly -> byte[] + abstract GetGeneratedAssemblyContents : assembly:Assembly -> byte array /// Represents additional, optional information for a type provider component type ITypeProvider2 = @@ -573,7 +573,7 @@ namespace Microsoft.FSharp.Core.CompilerServices /// A method returned by GetMethod on a provided type /// /// The static parameters of the provided method, if any - abstract GetStaticParametersForMethod : methodWithoutArguments:MethodBase -> ParameterInfo[] + abstract GetStaticParametersForMethod : methodWithoutArguments:MethodBase -> ParameterInfo array /// /// Apply static arguments to a provided method that accepts static arguments. @@ -584,4 +584,4 @@ namespace Microsoft.FSharp.Core.CompilerServices /// the values of the static parameters, indexed by name /// /// The provided method definition corresponding to the given static parameter values - abstract ApplyStaticArgumentsForMethod : methodWithoutArguments:MethodBase * methodNameWithArguments:string * staticArguments:obj[] -> MethodBase + abstract ApplyStaticArgumentsForMethod : methodWithoutArguments:MethodBase * methodNameWithArguments:string * staticArguments:obj array -> MethodBase diff --git a/src/FSharp.Core/list.fs b/src/FSharp.Core/list.fs index e3559a13958..dc81209a8c7 100644 --- a/src/FSharp.Core/list.fs +++ b/src/FSharp.Core/list.fs @@ -327,7 +327,7 @@ module List = loop state list1 list2 - let foldArraySubRight (f: OptimizedClosures.FSharpFunc<'T, _, _>) (arr: 'T[]) start fin acc = + let foldArraySubRight (f: OptimizedClosures.FSharpFunc<'T, _, _>) (arr: 'T array) start fin acc = let mutable state = acc for i = fin downto start do @@ -365,7 +365,7 @@ module List = let scanArraySubRight<'T, 'State> (f: OptimizedClosures.FSharpFunc<'T, 'State, 'State>) - (arr: _[]) + (arr: _ array) start fin initState diff --git a/src/FSharp.Core/list.fsi b/src/FSharp.Core/list.fsi index d746198f7fb..05ff605b247 100644 --- a/src/FSharp.Core/list.fsi +++ b/src/FSharp.Core/list.fsi @@ -1594,7 +1594,7 @@ module List = /// Evaluates to [ 1; 2; 5 ]. /// [] - val ofArray : array:'T[] -> 'T list + val ofArray : array:'T array -> 'T list /// Builds a new list from the given enumerable object. /// @@ -2176,7 +2176,7 @@ module List = /// Evaluates to [| 1; 2; 5 |]. /// [] - val toArray: list:'T list -> 'T[] + val toArray: list:'T list -> 'T array /// Views the given list as a sequence. /// diff --git a/src/FSharp.Core/local.fs b/src/FSharp.Core/local.fs index 70b1647cb4b..61f00c02aa3 100644 --- a/src/FSharp.Core/local.fs +++ b/src/FSharp.Core/local.fs @@ -193,7 +193,7 @@ module internal List = cons let groupBy (comparer:IEqualityComparer<'SafeKey>) (keyf:'T->'SafeKey) (getKey:'SafeKey->'Key) (list: 'T list) = - let dict = Dictionary<_, _ list []> comparer + let dict = Dictionary<_, _ list array> comparer // Build the groupings let rec loop list = diff --git a/src/FSharp.Core/local.fsi b/src/FSharp.Core/local.fsi index 9c2ebc0bbfd..1b210474062 100644 --- a/src/FSharp.Core/local.fsi +++ b/src/FSharp.Core/local.fsi @@ -72,10 +72,10 @@ module internal List = val splitInto: int -> 'T list -> 'T list list val zip: 'T1 list -> 'T2 list -> ('T1 * 'T2) list val zip3: 'T1 list -> 'T2 list -> 'T3 list -> ('T1 * 'T2 * 'T3) list - val ofArray: 'T[] -> 'T list + val ofArray: 'T array -> 'T list val take: int -> 'T list -> 'T list val takeWhile: ('T -> bool) -> 'T list -> 'T list - val toArray: 'T list -> 'T[] + val toArray: 'T list -> 'T array val inline ofSeq: seq<'T> -> 'T List val splitAt: int -> 'T list -> ('T list * 'T list) val transpose: 'T list list -> 'T list list @@ -84,40 +84,40 @@ module internal List = module internal Array = // The input parameter should be checked by callers if necessary - val inline zeroCreateUnchecked: int -> 'T[] + val inline zeroCreateUnchecked: int -> 'T array - val inline init: int -> (int -> 'T) -> 'T[] + val inline init: int -> (int -> 'T) -> 'T array - val splitInto: int -> 'T[] -> 'T[][] + val splitInto: int -> 'T array -> 'T array array - val findBack: predicate: ('T -> bool) -> array: 'T[] -> 'T + val findBack: predicate: ('T -> bool) -> array: 'T array -> 'T - val tryFindBack: predicate: ('T -> bool) -> array: 'T[] -> 'T option + val tryFindBack: predicate: ('T -> bool) -> array: 'T array -> 'T option - val findIndexBack: predicate: ('T -> bool) -> array: 'T[] -> int + val findIndexBack: predicate: ('T -> bool) -> array: 'T array -> int - val tryFindIndexBack: predicate: ('T -> bool) -> array: 'T[] -> int option + val tryFindIndexBack: predicate: ('T -> bool) -> array: 'T array -> int option - val mapFold: ('State -> 'T -> 'U * 'State) -> 'State -> 'T[] -> 'U[] * 'State + val mapFold: ('State -> 'T -> 'U * 'State) -> 'State -> 'T array -> 'U array * 'State - val mapFoldBack: ('T -> 'State -> 'U * 'State) -> 'T[] -> 'State -> 'U[] * 'State + val mapFoldBack: ('T -> 'State -> 'U * 'State) -> 'T array -> 'State -> 'U array * 'State - val permute: indexMap: (int -> int) -> 'T[] -> 'T[] + val permute: indexMap: (int -> int) -> 'T array -> 'T array val scanSubRight: - f: ('T -> 'State -> 'State) -> array: 'T[] -> start: int -> fin: int -> initState: 'State -> 'State[] + f: ('T -> 'State -> 'State) -> array: 'T array -> start: int -> fin: int -> initState: 'State -> 'State array - val inline subUnchecked: int -> int -> 'T[] -> 'T[] + val inline subUnchecked: int -> int -> 'T array -> 'T array - val unstableSortInPlaceBy: projection: ('T -> 'Key) -> array: 'T[] -> unit when 'Key: comparison + val unstableSortInPlaceBy: projection: ('T -> 'Key) -> array: 'T array -> unit when 'Key: comparison - val unstableSortInPlace: array: 'T[] -> unit when 'T: comparison + val unstableSortInPlace: array: 'T array -> unit when 'T: comparison - val stableSortInPlaceBy: projection: ('T -> 'Key) -> array: 'T[] -> unit when 'Key: comparison + val stableSortInPlaceBy: projection: ('T -> 'Key) -> array: 'T array -> unit when 'Key: comparison - val stableSortInPlaceWith: comparer: ('T -> 'T -> int) -> array: 'T[] -> unit + val stableSortInPlaceWith: comparer: ('T -> 'T -> int) -> array: 'T array -> unit - val stableSortInPlace: array: 'T[] -> unit when 'T: comparison + val stableSortInPlace: array: 'T array -> unit when 'T: comparison module internal Seq = val tryLastV: 'T seq -> 'T ValueOption diff --git a/src/FSharp.Core/map.fs b/src/FSharp.Core/map.fs index 35145ad8ec7..43459ecdf33 100644 --- a/src/FSharp.Core/map.fs +++ b/src/FSharp.Core/map.fs @@ -546,13 +546,13 @@ module MapTree = let ofSeq comparer (c: seq<'Key * 'T>) = match c with - | :? (('Key * 'T)[]) as xs -> ofArray comparer xs + | :? (('Key * 'T) array) as xs -> ofArray comparer xs | :? (('Key * 'T) list) as xs -> ofList comparer xs | _ -> use ie = c.GetEnumerator() mkFromEnumerator comparer empty ie - let copyToArray m (arr: _[]) i = + let copyToArray m (arr: _ array) i = let mutable j = i m diff --git a/src/FSharp.Core/map.fsi b/src/FSharp.Core/map.fsi index 49913cadbda..e6b0b1afb30 100644 --- a/src/FSharp.Core/map.fsi +++ b/src/FSharp.Core/map.fsi @@ -294,7 +294,7 @@ module Map = /// /// [] - val ofArray: elements: ('Key * 'T)[] -> Map<'Key, 'T> + val ofArray: elements: ('Key * 'T) array -> Map<'Key, 'T> /// Returns a new map made from the given bindings. /// @@ -361,7 +361,7 @@ module Map = /// /// [] - val toArray: table: Map<'Key, 'T> -> ('Key * 'T)[] + val toArray: table: Map<'Key, 'T> -> ('Key * 'T) array /// Is the map empty? /// diff --git a/src/FSharp.Core/option.fsi b/src/FSharp.Core/option.fsi index a3283345317..2aa2e315d51 100644 --- a/src/FSharp.Core/option.fsi +++ b/src/FSharp.Core/option.fsi @@ -380,7 +380,7 @@ module Option = /// /// [] - val inline toArray: option: 'T option -> 'T[] + val inline toArray: option: 'T option -> 'T array /// Convert the option to a list of length 0 or 1. /// @@ -838,7 +838,7 @@ module ValueOption = /// /// [] - val inline toArray: voption: 'T voption -> 'T[] + val inline toArray: voption: 'T voption -> 'T array /// Convert the value option to a list of length 0 or 1. /// diff --git a/src/FSharp.Core/prim-types-prelude.fsi b/src/FSharp.Core/prim-types-prelude.fsi index f9f8715c1ff..b9bbc5c125f 100644 --- a/src/FSharp.Core/prim-types-prelude.fsi +++ b/src/FSharp.Core/prim-types-prelude.fsi @@ -133,7 +133,7 @@ namespace Microsoft.FSharp.Core /// Basic Types type uint = uint32 - /// Single dimensional, zero-based arrays, written int[], string[] etc. + /// Single dimensional, zero-based arrays, written int array, string array etc. /// /// Use the values in the Array module to manipulate values /// of this type, or the notation arr.[x] to get/set array @@ -396,7 +396,7 @@ namespace Microsoft.FSharp.Core type 'T ``[,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,]`` = (# "!0[0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...,0 ...]" #) - /// Single dimensional, zero-based arrays, written int[], string[] etc. + /// Single dimensional, zero-based arrays, written int array, string array etc. /// /// Use the values in the module to manipulate values /// of this type, or the notation arr.[x] to get/set array diff --git a/src/FSharp.Core/prim-types.fs b/src/FSharp.Core/prim-types.fs index d44fa86610b..e1f64380f4a 100644 --- a/src/FSharp.Core/prim-types.fs +++ b/src/FSharp.Core/prim-types.fs @@ -225,7 +225,7 @@ namespace Microsoft.FSharp.Core variantNumber:int, sequenceNumber:int, resourceName:string, - typeDefinitions:System.Type[]) = + typeDefinitions:System.Type array) = inherit Attribute() member _.SourceConstructFlags = sourceConstructFlags member _.SequenceNumber = sequenceNumber @@ -272,7 +272,7 @@ namespace Microsoft.FSharp.Core [] [] - type CompilationArgumentCountsAttribute(counts:int[]) = + type CompilationArgumentCountsAttribute(counts:int array) = inherit Attribute() member _.Counts = let unboxPrim(x:obj) = (# "unbox.any !0" type ('T) x : 'T #) @@ -289,6 +289,7 @@ namespace Microsoft.FSharp.Core let mutable maintainsVarSpace = false let mutable maintainsVarSpaceWithBind = false let mutable joinOnWord = "" + new() = CustomOperationAttribute("") member _.Name = name member _.AllowIntoPattern with get() = allowInto and set v = allowInto <- v member _.IsLikeZip with get() = isBinary and set v = isBinary <- v @@ -525,10 +526,10 @@ namespace Microsoft.FSharp.Core let inline ignore _ = () let inline intOfByte (b:byte) = (# "" b : int #) let inline raise (e: System.Exception) = (# "throw" e : 'U #) - let inline length (x: 'T[]) = (# "ldlen conv.i4" x : int #) - let inline zeroCreate (n:int) = (# "newarr !0" type ('T) n : 'T[] #) - let inline get (arr: 'T[]) (n:int) = (# "ldelem.any !0" type ('T) arr n : 'T #) - let set (arr: 'T[]) (n:int) (x:'T) = (# "stelem.any !0" type ('T) arr n x #) + let inline length (x: 'T array) = (# "ldlen conv.i4" x : int #) + let inline zeroCreate (n:int) = (# "newarr !0" type ('T) n : 'T array #) + let inline get (arr: 'T array) (n:int) = (# "ldelem.any !0" type ('T) arr n : 'T #) + let set (arr: 'T array) (n:int) (x:'T) = (# "stelem.any !0" type ('T) arr n x #) let inline objEq (xobj:obj) (yobj:obj) = (# "ceq" xobj yobj : bool #) @@ -574,7 +575,7 @@ namespace Microsoft.FSharp.Core let inline opxor (x:int) (y:int) : int = (# "xor" x y : int32 #) let inline combineTupleHashes (h1 : int) (h2 : int) = (opxor ((opshl h1 5) + h1) h2) - let combineTupleHashCodes (codes : int []) = + let combineTupleHashCodes (codes : int array) = let mutable (num : int32) = codes.Length - 1 while (num > 1) do @@ -759,7 +760,7 @@ namespace Microsoft.FSharp.Core SetArray dst i (GetArray arr (start + i)) dst - let inline SetArraySub arr (start:int) (len:int) (src:_[]) = + let inline SetArraySub arr (start:int) (len:int) (src:_ array) = for i = 0 to len - 1 do SetArray arr (start+i) (GetArray src i) @@ -887,6 +888,123 @@ namespace Microsoft.FSharp.Core module HashCompare = + //------------------------------------------------------------------------- + // LanguagePrimitives.HashCompare: HASHING. + //------------------------------------------------------------------------- + + let defaultHashNodes = 18 + + /// The implementation of IEqualityComparer, using depth-limited for hashing and PER semantics for NaN equality. + type CountLimitedHasherPER(sz:int) = + [] + val mutable nodeCount : int + + member x.Fresh() = + if (System.Threading.Interlocked.CompareExchange(&(x.nodeCount), sz, 0) = 0) then + x + else + new CountLimitedHasherPER(sz) + + interface IEqualityComparer + + /// The implementation of IEqualityComparer, using unlimited depth for hashing and ER semantics for NaN equality. + type UnlimitedHasherER() = + interface IEqualityComparer + + /// The implementation of IEqualityComparer, using unlimited depth for hashing and PER semantics for NaN equality. + type UnlimitedHasherPER() = + interface IEqualityComparer + + + /// The unique object for unlimited depth for hashing and ER semantics for equality. + let fsEqualityComparerUnlimitedHashingER = UnlimitedHasherER() + + /// The unique object for unlimited depth for hashing and PER semantics for equality. + let fsEqualityComparerUnlimitedHashingPER = UnlimitedHasherPER() + + let inline HashCombine nr x y = (x <<< 1) + y + 631 * nr + + let GenericHashObjArray (iec : IEqualityComparer) (x: obj array) : int = + let len = x.Length + let mutable i = len - 1 + if i > defaultHashNodes then i <- defaultHashNodes // limit the hash + let mutable acc = 0 + while (i >= 0) do + // NOTE: GenericHash* call decreases nr + acc <- HashCombine i acc (iec.GetHashCode(x.GetValue(i))); + i <- i - 1 + acc + + // optimized case - byte arrays + let GenericHashByteArray (x: byte array) : int = + let len = length x + let mutable i = len - 1 + if i > defaultHashNodes then i <- defaultHashNodes // limit the hash + let mutable acc = 0 + while (i >= 0) do + acc <- HashCombine i acc (intOfByte (get x i)); + i <- i - 1 + acc + + // optimized case - int arrays + let GenericHashInt32Array (x: int array) : int = + let len = length x + let mutable i = len - 1 + if i > defaultHashNodes then i <- defaultHashNodes // limit the hash + let mutable acc = 0 + while (i >= 0) do + acc <- HashCombine i acc (get x i); + i <- i - 1 + acc + + // optimized case - int arrays + let GenericHashInt64Array (x: int64 array) : int = + let len = length x + let mutable i = len - 1 + if i > defaultHashNodes then i <- defaultHashNodes // limit the hash + let mutable acc = 0 + while (i >= 0) do + acc <- HashCombine i acc (int32 (get x i)); + i <- i - 1 + acc + + // special case - arrays do not by default have a decent structural hashing function + let GenericHashArbArray (iec : IEqualityComparer) (x: System.Array) : int = + match x.Rank with + | 1 -> + let b = x.GetLowerBound(0) + let len = x.Length + let mutable i = b + len - 1 + if i > b + defaultHashNodes then i <- b + defaultHashNodes // limit the hash + let mutable acc = 0 + while (i >= b) do + // NOTE: GenericHash* call decreases nr + acc <- HashCombine i acc (iec.GetHashCode(x.GetValue(i))); + i <- i - 1 + acc + | _ -> + HashCombine 10 (x.GetLength(0)) (x.GetLength(1)) + + // Core implementation of structural hashing, corresponds to pseudo-code in the + // F# Language spec. Searches for the IStructuralHash interface, otherwise uses GetHashCode(). + // Arrays are structurally hashed through a separate technique. + // + // "iec" is either fsEqualityComparerUnlimitedHashingER, fsEqualityComparerUnlimitedHashingPER or a CountLimitedHasherPER. + let rec GenericHashParamObj (iec : IEqualityComparer) (x: obj) : int = + match x with + | null -> 0 + | (:? System.Array as a) -> + match a with + | :? (obj array) as oa -> GenericHashObjArray iec oa + | :? (byte array) as ba -> GenericHashByteArray ba + | :? (int array) as ba -> GenericHashInt32Array ba + | :? (int64 array) as ba -> GenericHashInt64Array ba + | _ -> GenericHashArbArray iec a + | :? IStructuralEquatable as a -> + a.GetHashCode(iec) + | _ -> + x.GetHashCode() + //------------------------------------------------------------------------- // LanguagePrimitives.HashCompare: Physical Equality //------------------------------------------------------------------------- @@ -950,10 +1068,10 @@ namespace Microsoft.FSharp.Core | (:? System.Array as arr1),_ -> match arr1,yobj with // Fast path - | (:? (obj[]) as arr1), (:? (obj[]) as arr2) -> + | (:? (obj array) as arr1), (:? (obj array) as arr2) -> GenericComparisonObjArrayWithComparer comp arr1 arr2 // Fast path - | (:? (byte[]) as arr1), (:? (byte[]) as arr2) -> + | (:? (byte array) as arr1), (:? (byte array) as arr2) -> GenericComparisonByteArray arr1 arr2 | _, (:? System.Array as arr2) -> GenericComparisonArbArrayWithComparer comp arr1 arr2 @@ -1051,7 +1169,7 @@ namespace Microsoft.FSharp.Core precheck (k+1) let c = precheck 0 if c <> 0 then c else - let idxs : int64[] = zeroCreate ndims + let idxs : int64 array = zeroCreate ndims let rec checkN k baseIdx i lim = if i >=. lim then 0 else set idxs k (baseIdx +. i) @@ -1068,7 +1186,7 @@ namespace Microsoft.FSharp.Core check 0 /// optimized case: Core implementation of structural comparison on object arrays. - and GenericComparisonObjArrayWithComparer (comp:GenericComparer) (x:obj[]) (y:obj[]) : int = + and GenericComparisonObjArrayWithComparer (comp:GenericComparer) (x:obj array) (y:obj array) : int = let lenx = x.Length let leny = y.Length let c = intOrder lenx leny @@ -1083,7 +1201,7 @@ namespace Microsoft.FSharp.Core res /// optimized case: Core implementation of structural comparison on arrays. - and GenericComparisonByteArray (x:byte[]) (y:byte[]) : int = + and GenericComparisonByteArray (x:byte array) (y:byte array) : int = let lenx = x.Length let leny = y.Length let c = intOrder lenx leny @@ -1334,7 +1452,7 @@ namespace Microsoft.FSharp.Core /// optimized case: Core implementation of structural equality on arrays. - let GenericEqualityByteArray (x:byte[]) (y:byte[]) : bool= + let GenericEqualityByteArray (x:byte array) (y:byte array) : bool= let lenx = x.Length let leny = y.Length let c = (lenx = leny) @@ -1349,7 +1467,7 @@ namespace Microsoft.FSharp.Core res /// optimized case: Core implementation of structural equality on arrays. - let GenericEqualityInt32Array (x:int[]) (y:int[]) : bool= + let GenericEqualityInt32Array (x:int array) (y:int array) : bool= let lenx = x.Length let leny = y.Length let c = (lenx = leny) @@ -1364,7 +1482,7 @@ namespace Microsoft.FSharp.Core res /// optimized case: Core implementation of structural equality on arrays - let GenericEqualitySingleArray er (x:float32[]) (y:float32[]) : bool= + let GenericEqualitySingleArray er (x:float32 array) (y:float32 array) : bool= let lenx = x.Length let leny = y.Length let f32eq x y = if er && not(float32Eq x x) && not(float32Eq y y) then true else (float32Eq x y) @@ -1380,7 +1498,7 @@ namespace Microsoft.FSharp.Core res /// optimized case: Core implementation of structural equality on arrays. - let GenericEqualityDoubleArray er (x:float[]) (y:float[]) : bool= + let GenericEqualityDoubleArray er (x:float array) (y:float array) : bool= let lenx = x.Length let leny = y.Length let c = (lenx = leny) @@ -1396,7 +1514,7 @@ namespace Microsoft.FSharp.Core res /// optimized case: Core implementation of structural equality on arrays. - let GenericEqualityCharArray (x:char[]) (y:char[]) : bool= + let GenericEqualityCharArray (x:char array) (y:char array) : bool= let lenx = x.Length let leny = y.Length let c = (lenx = leny) @@ -1411,7 +1529,7 @@ namespace Microsoft.FSharp.Core res /// optimized case: Core implementation of structural equality on arrays. - let GenericEqualityInt64Array (x:int64[]) (y:int64[]) : bool= + let GenericEqualityInt64Array (x:int64 array) (y:int64 array) : bool= let lenx = x.Length let leny = y.Length let c = (lenx = leny) @@ -1446,14 +1564,14 @@ namespace Microsoft.FSharp.Core | (:? System.Array as arr1),_ -> match arr1,yobj with // Fast path - | (:? (obj[]) as arr1), (:? (obj[]) as arr2) -> GenericEqualityObjArray er iec arr1 arr2 + | (:? (obj array) as arr1), (:? (obj array) as arr2) -> GenericEqualityObjArray er iec arr1 arr2 // Fast path - | (:? (byte[]) as arr1), (:? (byte[]) as arr2) -> GenericEqualityByteArray arr1 arr2 - | (:? (int32[]) as arr1), (:? (int32[]) as arr2) -> GenericEqualityInt32Array arr1 arr2 - | (:? (int64[]) as arr1), (:? (int64[]) as arr2) -> GenericEqualityInt64Array arr1 arr2 - | (:? (char[]) as arr1), (:? (char[]) as arr2) -> GenericEqualityCharArray arr1 arr2 - | (:? (float32[]) as arr1), (:? (float32[]) as arr2) -> GenericEqualitySingleArray er arr1 arr2 - | (:? (float[]) as arr1), (:? (float[]) as arr2) -> GenericEqualityDoubleArray er arr1 arr2 + | (:? (byte array) as arr1), (:? (byte array) as arr2) -> GenericEqualityByteArray arr1 arr2 + | (:? (int32 array) as arr1), (:? (int32 array) as arr2) -> GenericEqualityInt32Array arr1 arr2 + | (:? (int64 array) as arr1), (:? (int64 array) as arr2) -> GenericEqualityInt64Array arr1 arr2 + | (:? (char array) as arr1), (:? (char array) as arr2) -> GenericEqualityCharArray arr1 arr2 + | (:? (float32 array) as arr1), (:? (float32 array) as arr2) -> GenericEqualitySingleArray er arr1 arr2 + | (:? (float array) as arr1), (:? (float array) as arr2) -> GenericEqualityDoubleArray er arr1 arr2 | _, (:? System.Array as arr2) -> GenericEqualityArbArray er iec arr1 arr2 | _ -> xobj.Equals(yobj) | (:? IStructuralEquatable as x1),_ -> x1.Equals(yobj,iec) @@ -1508,7 +1626,7 @@ namespace Microsoft.FSharp.Core int32Eq (x.GetLowerBound(k)) (y.GetLowerBound(k)) && precheck (k+1)) precheck 0 && - let idxs : int64[] = zeroCreate ndims + let idxs : int64 array = zeroCreate ndims // check contents let rec checkN k baseIdx i lim = (i >=. lim) || @@ -1524,7 +1642,7 @@ namespace Microsoft.FSharp.Core check 0 /// optimized case: Core implementation of structural equality on object arrays. - and GenericEqualityObjArray er iec (x:obj[]) (y:obj[]) : bool = + and GenericEqualityObjArray er iec (x:obj array) (y:obj array) : bool = let lenx = x.Length let leny = y.Length let c = (lenx = leny ) @@ -1664,126 +1782,6 @@ namespace Microsoft.FSharp.Core when 'T : decimal = System.Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #)) when 'T : DateTime = DateTime.Equals((# "" x : DateTime #), (# "" y : DateTime #)) - //------------------------------------------------------------------------- - // LanguagePrimitives.HashCompare: HASHING. - //------------------------------------------------------------------------- - - - - let defaultHashNodes = 18 - - /// The implementation of IEqualityComparer, using depth-limited for hashing and PER semantics for NaN equality. - type CountLimitedHasherPER(sz:int) = - [] - val mutable nodeCount : int - - member x.Fresh() = - if (System.Threading.Interlocked.CompareExchange(&(x.nodeCount), sz, 0) = 0) then - x - else - new CountLimitedHasherPER(sz) - - interface IEqualityComparer - - /// The implementation of IEqualityComparer, using unlimited depth for hashing and ER semantics for NaN equality. - type UnlimitedHasherER() = - interface IEqualityComparer - - /// The implementation of IEqualityComparer, using unlimited depth for hashing and PER semantics for NaN equality. - type UnlimitedHasherPER() = - interface IEqualityComparer - - - /// The unique object for unlimited depth for hashing and ER semantics for equality. - let fsEqualityComparerUnlimitedHashingER = UnlimitedHasherER() - - /// The unique object for unlimited depth for hashing and PER semantics for equality. - let fsEqualityComparerUnlimitedHashingPER = UnlimitedHasherPER() - - let inline HashCombine nr x y = (x <<< 1) + y + 631 * nr - - let GenericHashObjArray (iec : IEqualityComparer) (x: obj[]) : int = - let len = x.Length - let mutable i = len - 1 - if i > defaultHashNodes then i <- defaultHashNodes // limit the hash - let mutable acc = 0 - while (i >= 0) do - // NOTE: GenericHash* call decreases nr - acc <- HashCombine i acc (iec.GetHashCode(x.GetValue(i))); - i <- i - 1 - acc - - // optimized case - byte arrays - let GenericHashByteArray (x: byte[]) : int = - let len = length x - let mutable i = len - 1 - if i > defaultHashNodes then i <- defaultHashNodes // limit the hash - let mutable acc = 0 - while (i >= 0) do - acc <- HashCombine i acc (intOfByte (get x i)); - i <- i - 1 - acc - - // optimized case - int arrays - let GenericHashInt32Array (x: int[]) : int = - let len = length x - let mutable i = len - 1 - if i > defaultHashNodes then i <- defaultHashNodes // limit the hash - let mutable acc = 0 - while (i >= 0) do - acc <- HashCombine i acc (get x i); - i <- i - 1 - acc - - // optimized case - int arrays - let GenericHashInt64Array (x: int64[]) : int = - let len = length x - let mutable i = len - 1 - if i > defaultHashNodes then i <- defaultHashNodes // limit the hash - let mutable acc = 0 - while (i >= 0) do - acc <- HashCombine i acc (int32 (get x i)); - i <- i - 1 - acc - - // special case - arrays do not by default have a decent structural hashing function - let GenericHashArbArray (iec : IEqualityComparer) (x: System.Array) : int = - match x.Rank with - | 1 -> - let b = x.GetLowerBound(0) - let len = x.Length - let mutable i = b + len - 1 - if i > b + defaultHashNodes then i <- b + defaultHashNodes // limit the hash - let mutable acc = 0 - while (i >= b) do - // NOTE: GenericHash* call decreases nr - acc <- HashCombine i acc (iec.GetHashCode(x.GetValue(i))); - i <- i - 1 - acc - | _ -> - HashCombine 10 (x.GetLength(0)) (x.GetLength(1)) - - // Core implementation of structural hashing, corresponds to pseudo-code in the - // F# Language spec. Searches for the IStructuralHash interface, otherwise uses GetHashCode(). - // Arrays are structurally hashed through a separate technique. - // - // "iec" is either fsEqualityComparerUnlimitedHashingER, fsEqualityComparerUnlimitedHashingPER or a CountLimitedHasherPER. - let rec GenericHashParamObj (iec : IEqualityComparer) (x: obj) : int = - match x with - | null -> 0 - | (:? System.Array as a) -> - match a with - | :? (obj[]) as oa -> GenericHashObjArray iec oa - | :? (byte[]) as ba -> GenericHashByteArray ba - | :? (int[]) as ba -> GenericHashInt32Array ba - | :? (int64[]) as ba -> GenericHashInt64Array ba - | _ -> GenericHashArbArray iec a - | :? IStructuralEquatable as a -> - a.GetHashCode(iec) - | _ -> - x.GetHashCode() - - /// Fill in the implementation of CountLimitedHasherPER type CountLimitedHasherPER with @@ -2602,7 +2600,7 @@ namespace Microsoft.FSharp.Core type Type with /// Gets a single static non-conversion operator or method by types - member inline this.GetSingleStaticMethodByTypes(name: string, parameterTypes: Type[]) = + member inline this.GetSingleStaticMethodByTypes(name: string, parameterTypes: Type array) = let staticBindingFlags = (# "" 0b111000 : BindingFlags #) // BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic this.GetMethod(name, staticBindingFlags, null, parameterTypes, null ) @@ -4002,7 +4000,7 @@ namespace Microsoft.FSharp.Collections let items length = let items = zeroCreate length - let rec copy (items: 'T[]) l i = + let rec copy (items: 'T array) l i = match l with | [] -> () | h :: t -> @@ -6039,11 +6037,11 @@ namespace Microsoft.FSharp.Core low, high - let inline GetArraySlice (source: _[]) start finish = + let inline GetArraySlice (source: _ array) start finish = let start, finish = ComputeSlice 0 start finish source.Length GetArraySub source start (finish - start + 1) - let inline SetArraySlice (target: _[]) start finish (source: _[]) = + let inline SetArraySlice (target: _ array) start finish (source: _ array) = let start = (match start with None -> 0 | Some n -> n) let finish = (match finish with None -> target.Length - 1 | Some n -> n) SetArraySub target start (finish - start + 1) source @@ -6075,7 +6073,7 @@ namespace Microsoft.FSharp.Core let inline GetArraySlice2DFixed2 (source: _[,]) start1 finish1 index2 = GetArraySlice2DFixed source start1 finish1 index2 0 - let inline SetArraySlice2DFixed (target: _[,]) (source: _[]) index start finish nonFixedDim = + let inline SetArraySlice2DFixed (target: _[,]) (source: _ array) index start finish nonFixedDim = let bound = target.GetLowerBound(nonFixedDim) let start, finish = ComputeSlice bound start finish (GetArray2DLength target nonFixedDim) let len = (finish - start + 1) @@ -6087,9 +6085,9 @@ namespace Microsoft.FSharp.Core for j = 0 to len - 1 do setArrayElem j - let inline SetArraySlice2DFixed1 (target: _[,]) index1 start2 finish2 (source: _[]) = SetArraySlice2DFixed target source index1 start2 finish2 1 + let inline SetArraySlice2DFixed1 (target: _[,]) index1 start2 finish2 (source: _ array) = SetArraySlice2DFixed target source index1 start2 finish2 1 - let inline SetArraySlice2DFixed2 (target: _[,]) start1 finish1 index2 (source:_[]) = SetArraySlice2DFixed target source index2 start1 finish1 0 + let inline SetArraySlice2DFixed2 (target: _[,]) start1 finish1 index2 (source:_ array) = SetArraySlice2DFixed target source index2 start1 finish1 0 let inline SetArraySlice2D (target: _[,]) start1 finish1 start2 finish2 (source: _[,]) = let bound1 = target.GetLowerBound(0) @@ -6203,7 +6201,7 @@ namespace Microsoft.FSharp.Core let inline SetArraySlice3DFixedSingle3 (target: _[,,]) start1 finish1 start2 finish2 index (source: _[,]) = SetArraySlice3DFixedSingle target source index start1 finish1 start2 finish2 0 1 - let inline SetArraySlice3DFixedDouble (target: _[,,]) (source: _[]) index1 index2 start finish nonFixedDim = + let inline SetArraySlice3DFixedDouble (target: _[,,]) (source: _ array) index1 index2 start finish nonFixedDim = let bound = target.GetLowerBound(nonFixedDim) let start, finish = ComputeSlice bound start finish (GetArray3DLength target nonFixedDim) let len = (finish - start + 1) @@ -6216,13 +6214,13 @@ namespace Microsoft.FSharp.Core for j = 0 to len - 1 do setArrayElem j - let inline SetArraySlice3DFixedDouble1 (target: _[,,]) index1 index2 start3 finish3 (source: _[]) = + let inline SetArraySlice3DFixedDouble1 (target: _[,,]) index1 index2 start3 finish3 (source: _ array) = SetArraySlice3DFixedDouble target source index1 index2 start3 finish3 2 - let inline SetArraySlice3DFixedDouble2 (target: _[,,]) index1 start2 finish2 index3 (source: _[]) = + let inline SetArraySlice3DFixedDouble2 (target: _[,,]) index1 start2 finish2 index3 (source: _ array) = SetArraySlice3DFixedDouble target source index1 index3 start2 finish2 1 - let inline SetArraySlice3DFixedDouble3 (target: _[,,]) start1 finish1 index2 index3 (source: _[]) = + let inline SetArraySlice3DFixedDouble3 (target: _[,,]) start1 finish1 index2 index3 (source: _ array) = SetArraySlice3DFixedDouble target source index2 index3 start1 finish1 0 let inline GetArraySlice4D (source: _[,,,]) start1 finish1 start2 finish2 start3 finish3 start4 finish4 = @@ -6440,7 +6438,7 @@ namespace Microsoft.FSharp.Core let inline SetArraySlice4DFixedDouble6 (target: _[,,,]) start1 finish1 start2 finish2 index3 index4 (source: _[,]) = SetArraySlice4DFixedDouble target source index3 index4 start1 finish1 start2 finish2 0 1 - let inline SetArraySlice4DFixedTriple (target: _[,,,]) (source: _[]) index1 index2 index3 start1 finish1 nonFixedDim1 = + let inline SetArraySlice4DFixedTriple (target: _[,,,]) (source: _ array) index1 index2 index3 start1 finish1 nonFixedDim1 = let bound1 = target.GetLowerBound(nonFixedDim1) let start1, finish1 = ComputeSlice bound1 start1 finish1 (GetArray4DLength target nonFixedDim1) let len1 = (finish1 - start1 + 1) @@ -6454,16 +6452,16 @@ namespace Microsoft.FSharp.Core for i = 0 to len1 - 1 do setArrayElem i - let inline SetArraySlice4DFixedTriple1 (target: _[,,,]) start1 finish1 index2 index3 index4 (source: _[]) = + let inline SetArraySlice4DFixedTriple1 (target: _[,,,]) start1 finish1 index2 index3 index4 (source: _ array) = SetArraySlice4DFixedTriple target source index2 index3 index4 start1 finish1 0 - let inline SetArraySlice4DFixedTriple2 (target: _[,,,]) index1 start2 finish2 index3 index4 (source: _[]) = + let inline SetArraySlice4DFixedTriple2 (target: _[,,,]) index1 start2 finish2 index3 index4 (source: _ array) = SetArraySlice4DFixedTriple target source index1 index3 index4 start2 finish2 1 - let inline SetArraySlice4DFixedTriple3 (target: _[,,,]) index1 index2 start3 finish3 index4 (source: _[]) = + let inline SetArraySlice4DFixedTriple3 (target: _[,,,]) index1 index2 start3 finish3 index4 (source: _ array) = SetArraySlice4DFixedTriple target source index1 index2 index4 start3 finish3 2 - let inline SetArraySlice4DFixedTriple4 (target: _[,,,]) index1 index2 index3 start4 finish4 (source: _[]) = + let inline SetArraySlice4DFixedTriple4 (target: _[,,,]) index1 index2 index3 start4 finish4 (source: _ array) = SetArraySlice4DFixedTriple target source index1 index2 index3 start4 finish4 3 let inline GetStringSlice (source: string) start finish = diff --git a/src/FSharp.Core/prim-types.fsi b/src/FSharp.Core/prim-types.fsi index 13fb9e46ff9..e3c2bb245b6 100644 --- a/src/FSharp.Core/prim-types.fsi +++ b/src/FSharp.Core/prim-types.fsi @@ -420,6 +420,10 @@ namespace Microsoft.FSharp.Core /// CustomOperationAttribute new: name:string -> CustomOperationAttribute + /// Create an instance of attribute with empty name + /// CustomOperationAttribute + new: unit -> CustomOperationAttribute + /// Get the name of the custom operation when used in a query or other computation expression member Name: string @@ -687,7 +691,7 @@ namespace Microsoft.FSharp.Core /// The name of the resource needed to resolve the source construct. /// /// CompilationMappingAttribute - new: resourceName:string * typeDefinitions:System.Type[] -> CompilationMappingAttribute + new: resourceName:string * typeDefinitions:System.Type array -> CompilationMappingAttribute /// Indicates the relationship between the compiled entity and F# source code member SourceConstructFlags: SourceConstructFlags @@ -702,7 +706,7 @@ namespace Microsoft.FSharp.Core member ResourceName: string /// Indicates the type definitions needed to resolve the source construct - member TypeDefinitions: System.Type[] + member TypeDefinitions: System.Type array /// This attribute is inserted automatically by the F# compiler to tag /// methods which are given the 'CompiledName' attribute. @@ -805,7 +809,7 @@ namespace Microsoft.FSharp.Core /// Indicates the number of arguments in each argument group. /// /// CompilationArgumentCountsAttribute - new: counts:int[] -> CompilationArgumentCountsAttribute + new: counts:int array -> CompilationArgumentCountsAttribute /// Indicates the number of arguments in each argument group member Counts: System.Collections.Generic.IEnumerable @@ -1785,7 +1789,7 @@ namespace Microsoft.FSharp.Core /// The standard overloaded associative (indexed) lookup operator //[] - val inline GetArray: source: 'T[] -> index: int -> 'T + val inline GetArray: source: 'T array -> index: int -> 'T /// The standard overloaded associative (2-indexed) lookup operator //[] @@ -1801,7 +1805,7 @@ namespace Microsoft.FSharp.Core /// The standard overloaded associative (indexed) mutation operator //[] - val inline SetArray: target: 'T[] -> index: int -> value: 'T -> unit + val inline SetArray: target: 'T array -> index: int -> value: 'T -> unit /// The standard overloaded associative (2-indexed) mutation operator //[] @@ -4859,7 +4863,7 @@ namespace Microsoft.FSharp.Core /// The end index. /// /// The sub array from the input indices. - val inline GetArraySlice: source:'T[] -> start:int option -> finish:int option -> 'T[] + val inline GetArraySlice: source:'T array -> start:int option -> finish:int option -> 'T array /// Sets a slice of an array /// @@ -4867,7 +4871,7 @@ namespace Microsoft.FSharp.Core /// The start index. /// The end index. /// The source array. - val inline SetArraySlice: target:'T[] -> start:int option -> finish:int option -> source:'T[] -> unit + val inline SetArraySlice: target:'T array -> start:int option -> finish:int option -> source:'T array -> unit /// Gets a region slice of an array /// @@ -4888,7 +4892,7 @@ namespace Microsoft.FSharp.Core /// The end index of the second dimension. /// /// The sub array from the input indices. - val inline GetArraySlice2DFixed1: source:'T[,] -> index1:int -> start2:int option -> finish2:int option -> 'T[] + val inline GetArraySlice2DFixed1: source:'T[,] -> index1:int -> start2:int option -> finish2:int option -> 'T array /// Gets a vector slice of a 2D array. The index of the second dimension is fixed. /// @@ -4898,7 +4902,7 @@ namespace Microsoft.FSharp.Core /// The fixed index of the second dimension. /// /// The sub array from the input indices. - val inline GetArraySlice2DFixed2: source:'T[,] -> start1:int option -> finish1:int option -> index2: int -> 'T[] + val inline GetArraySlice2DFixed2: source:'T[,] -> start1:int option -> finish1:int option -> index2: int -> 'T array /// Sets a region slice of an array /// @@ -4917,7 +4921,7 @@ namespace Microsoft.FSharp.Core /// The start index of the second dimension. /// The end index of the second dimension. /// The source array. - val inline SetArraySlice2DFixed1: target:'T[,] -> index1:int -> start2:int option -> finish2:int option -> source:'T[] -> unit + val inline SetArraySlice2DFixed1: target:'T[,] -> index1:int -> start2:int option -> finish2:int option -> source:'T array -> unit /// Sets a vector slice of a 2D array. The index of the second dimension is fixed. /// @@ -4926,7 +4930,7 @@ namespace Microsoft.FSharp.Core /// The end index of the first dimension. /// The index of the second dimension. /// The source array. - val inline SetArraySlice2DFixed2: target:'T[,] -> start1:int option -> finish1:int option -> index2:int -> source:'T[] -> unit + val inline SetArraySlice2DFixed2: target:'T[,] -> start1:int option -> finish1:int option -> index2:int -> source:'T array -> unit /// Gets a slice of an array /// @@ -4986,7 +4990,7 @@ namespace Microsoft.FSharp.Core /// The end index of the third dimension. /// /// The one dimensional sub array from the given indices. - val inline GetArraySlice3DFixedDouble1: source:'T[,,] -> index1:int -> index2:int -> start3:int option -> finish3:int option -> 'T[] + val inline GetArraySlice3DFixedDouble1: source:'T[,,] -> index1:int -> index2:int -> start3:int option -> finish3:int option -> 'T array /// Gets a 1D slice of a 3D array. /// @@ -4997,7 +5001,7 @@ namespace Microsoft.FSharp.Core /// The fixed index of the third dimension. /// /// The one dimensional sub array from the given indices. - val inline GetArraySlice3DFixedDouble2: source:'T[,,] -> index1:int -> start2:int option -> finish2:int option -> index3:int -> 'T[] + val inline GetArraySlice3DFixedDouble2: source:'T[,,] -> index1:int -> start2:int option -> finish2:int option -> index3:int -> 'T array /// Gets a 1D slice of a 3D array. /// @@ -5008,7 +5012,7 @@ namespace Microsoft.FSharp.Core /// The fixed index of the third dimension. /// /// The one dimensional sub array from the given indices. - val inline GetArraySlice3DFixedDouble3: source:'T[,,] -> start1:int option -> finish1:int option -> index2:int -> index3:int -> 'T[] + val inline GetArraySlice3DFixedDouble3: source:'T[,,] -> start1:int option -> finish1:int option -> index2:int -> index3:int -> 'T array /// Sets a slice of an array /// @@ -5071,7 +5075,7 @@ namespace Microsoft.FSharp.Core /// The source array. /// /// The one dimensional sub array from the given indices. - val inline SetArraySlice3DFixedDouble1: target: 'T[,,] -> index1: int -> index2: int -> start3: int option -> finish3: int option -> source: 'T[] -> unit + val inline SetArraySlice3DFixedDouble1: target: 'T[,,] -> index1: int -> index2: int -> start3: int option -> finish3: int option -> source: 'T array -> unit /// Sets a 1D slice of a 3D array. /// @@ -5083,7 +5087,7 @@ namespace Microsoft.FSharp.Core /// The source array. /// /// The one dimensional sub array from the given indices. - val inline SetArraySlice3DFixedDouble2: target: 'T[,,] -> index1: int -> start2: int option -> finish2: int option -> index3: int -> source: 'T[] -> unit + val inline SetArraySlice3DFixedDouble2: target: 'T[,,] -> index1: int -> start2: int option -> finish2: int option -> index3: int -> source: 'T array -> unit /// Sets a 1D slice of a 3D array. /// @@ -5095,7 +5099,7 @@ namespace Microsoft.FSharp.Core /// The source array. /// /// The one dimensional sub array from the given indices. - val inline SetArraySlice3DFixedDouble3: target: 'T[,,] -> start1: int option -> finish1: int option -> index2: int -> index3: int -> source: 'T[] -> unit + val inline SetArraySlice3DFixedDouble3: target: 'T[,,] -> start1: int option -> finish1: int option -> index2: int -> index3: int -> source: 'T array -> unit /// Gets a slice of an array /// @@ -5256,7 +5260,7 @@ namespace Microsoft.FSharp.Core /// The end index of the fourth dimension. /// /// The one dimensional sub array from the given indices. - val inline GetArraySlice4DFixedTriple4: source: 'T[,,,] -> index1: int -> index2: int -> index3: int -> start4: int option -> finish4: int option -> 'T[] + val inline GetArraySlice4DFixedTriple4: source: 'T[,,,] -> index1: int -> index2: int -> index3: int -> start4: int option -> finish4: int option -> 'T array /// Gets a 1D slice of a 4D array /// @@ -5268,7 +5272,7 @@ namespace Microsoft.FSharp.Core /// The fixed index of the fourth dimension. /// /// The one dimensional sub array from the given indices. - val inline GetArraySlice4DFixedTriple3: source: 'T[,,,] -> index1: int -> index2: int -> start3: int option -> finish3: int option -> index4: int -> 'T[] + val inline GetArraySlice4DFixedTriple3: source: 'T[,,,] -> index1: int -> index2: int -> start3: int option -> finish3: int option -> index4: int -> 'T array /// Gets a 1D slice of a 4D array /// @@ -5280,7 +5284,7 @@ namespace Microsoft.FSharp.Core /// The fixed index of the fourth dimension. /// /// The one dimensional sub array from the given indices. - val inline GetArraySlice4DFixedTriple2: source:'T[,,,] -> index1: int -> start2: int option -> finish2: int option -> index3: int -> index4: int -> 'T[] + val inline GetArraySlice4DFixedTriple2: source:'T[,,,] -> index1: int -> start2: int option -> finish2: int option -> index3: int -> index4: int -> 'T array /// Gets a 1D slice of a 4D array /// @@ -5292,7 +5296,7 @@ namespace Microsoft.FSharp.Core /// The fixed index of the fourth dimension. /// /// The one dimensional sub array from the given indices. - val inline GetArraySlice4DFixedTriple1: source: 'T[,,,] -> start1: int option -> finish1: int option -> index2: int -> index3: int -> index4: int -> 'T[] + val inline GetArraySlice4DFixedTriple1: source: 'T[,,,] -> start1: int option -> finish1: int option -> index2: int -> index3: int -> index4: int -> 'T array /// Sets a 3D slice of a 4D array /// @@ -5427,7 +5431,7 @@ namespace Microsoft.FSharp.Core /// The start index of the fourth dimension. /// The end index of the fourth dimension. /// The source array. - val inline SetArraySlice4DFixedTriple4: target:'T[,,,] -> index1:int -> index2:int -> index3:int -> start4:int option -> finish4:int option -> source: 'T[] -> unit + val inline SetArraySlice4DFixedTriple4: target:'T[,,,] -> index1:int -> index2:int -> index3:int -> start4:int option -> finish4:int option -> source: 'T array -> unit /// Sets a 1D slice of a 4D array /// @@ -5438,7 +5442,7 @@ namespace Microsoft.FSharp.Core /// The end index of the third dimension. /// The fixed index of the fourth dimension. /// The source array. - val inline SetArraySlice4DFixedTriple3: target:'T[,,,] -> index1:int -> index2:int -> start3:int option -> finish3:int option -> index4:int -> source: 'T[] -> unit + val inline SetArraySlice4DFixedTriple3: target:'T[,,,] -> index1:int -> index2:int -> start3:int option -> finish3:int option -> index4:int -> source: 'T array -> unit /// Sets a 1D slice of a 4D array /// @@ -5449,7 +5453,7 @@ namespace Microsoft.FSharp.Core /// The fixed index of the third dimension. /// The fixed index of the fourth dimension. /// The source array. - val inline SetArraySlice4DFixedTriple2: target:'T[,,,] -> index1:int -> start2: int option -> finish2:int option -> index3:int -> index4:int -> source: 'T[] -> unit + val inline SetArraySlice4DFixedTriple2: target:'T[,,,] -> index1:int -> start2: int option -> finish2:int option -> index3:int -> index4:int -> source: 'T array -> unit /// Sets a 1D slice of a 4D array /// @@ -5460,7 +5464,7 @@ namespace Microsoft.FSharp.Core /// The fixed index of the third dimension. /// The fixed index of the fourth dimension. /// The source array. - val inline SetArraySlice4DFixedTriple1: target:'T[,,,] -> start1:int option -> finish1:int option -> index2:int -> index3:int -> index4:int -> source: 'T[] -> unit + val inline SetArraySlice4DFixedTriple1: target:'T[,,,] -> start1:int option -> finish1:int option -> index2:int -> index3:int -> index4:int -> source: 'T array -> unit /// Sets a slice of an array /// diff --git a/src/FSharp.Core/printf.fs b/src/FSharp.Core/printf.fs index 9a7d461d698..7afcce1e66b 100644 --- a/src/FSharp.Core/printf.fs +++ b/src/FSharp.Core/printf.fs @@ -19,7 +19,7 @@ open LanguagePrimitives.IntrinsicOperators type PrintfFormat<'Printer, 'State, 'Residue, 'Result> [] - (value:string, captures: obj[], captureTys: Type[]) = + (value:string, captures: obj array, captureTys: Type array) = [] new (value) = new PrintfFormat<'Printer, 'State, 'Residue, 'Result>(value, null, null) @@ -34,7 +34,7 @@ type PrintfFormat<'Printer, 'State, 'Residue, 'Result> type PrintfFormat<'Printer, 'State, 'Residue, 'Result, 'Tuple> [] - (value:string, captures, captureTys: Type[]) = + (value:string, captures, captureTys: Type array) = inherit PrintfFormat<'Printer, 'State, 'Residue, 'Result>(value, captures, captureTys) @@ -274,7 +274,7 @@ module internal PrintfImpl = | StepPercentStar2 of prefix: string // Count the number of string fragments in a sequence of steps - static member BlockCount(steps: Step[]) = + static member BlockCount(steps: Step array) = let mutable count = 0 for step in steps do match step with @@ -323,7 +323,7 @@ module internal PrintfImpl = if not (String.IsNullOrEmpty s) then env.Write s - member env.RunSteps (args: obj[], argTys: Type[], steps: Step[]) = + member env.RunSteps (args: obj array, argTys: Type array, steps: Step array) = let mutable argIndex = 0 let mutable tyIndex = 0 @@ -1029,7 +1029,7 @@ module internal PrintfImpl = type LargeStringPrintfEnv<'Result>(continuation, blockSize) = inherit PrintfEnv(()) - let buf: string[] = Array.zeroCreate blockSize + let buf: string array = Array.zeroCreate blockSize let mutable ptr = 0 override _.Finish() : 'Result = continuation (String.Concat buf) @@ -1089,8 +1089,8 @@ module internal PrintfImpl = [] type FormatParser<'Printer, 'State, 'Residue, 'Result>(fmt: string) = - let buildCaptureFunc (spec: FormatSpecifier, allSteps, argTys: Type[], retTy, nextInfo) = - let (next:obj, nextCanCombine: bool, nextArgTys: Type[], nextRetTy, nextNextOpt) = nextInfo + let buildCaptureFunc (spec: FormatSpecifier, allSteps, argTys: Type array, retTy, nextInfo) = + let (next:obj, nextCanCombine: bool, nextArgTys: Type array, nextRetTy, nextNextOpt) = nextInfo assert (argTys.Length > 0) // See if we can compress a capture to a multi-capture @@ -1133,7 +1133,7 @@ module internal PrintfImpl = let factoryObj = mi.Invoke(null, [| next |]) factoryObj, true, argTys, retTy, Some next - let buildStep (spec: FormatSpecifier) (argTys: Type[]) prefix = + let buildStep (spec: FormatSpecifier) (argTys: Type array) prefix = if spec.TypeChar = 'a' then StepLittleA prefix elif spec.TypeChar = 't' then diff --git a/src/FSharp.Core/printf.fsi b/src/FSharp.Core/printf.fsi index a188e570183..2e4d009c537 100644 --- a/src/FSharp.Core/printf.fsi +++ b/src/FSharp.Core/printf.fsi @@ -30,16 +30,18 @@ type PrintfFormat<'Printer, 'State, 'Residue, 'Result> = /// The captured expressions in an interpolated string. /// The types of expressions for %A expression gaps in interpolated string. /// The PrintfFormat containing the formatted result. - new: value: string * captures: obj[] * captureTys: Type[] -> PrintfFormat<'Printer, 'State, 'Residue, 'Result> + new: + value: string * captures: obj array * captureTys: Type array -> + PrintfFormat<'Printer, 'State, 'Residue, 'Result> /// The raw text of the format string. member Value: string /// The captures associated with an interpolated string. - member Captures: obj[] + member Captures: obj array /// The capture types associated with an interpolated string. - member CaptureTypes: System.Type[] + member CaptureTypes: System.Type array /// Type of a formatting expression. /// @@ -69,7 +71,7 @@ type PrintfFormat<'Printer, 'State, 'Residue, 'Result, 'Tuple> = /// /// The created format string. new: - value: string * captures: obj[] * captureTys: Type[] -> + value: string * captures: obj array * captureTys: Type array -> PrintfFormat<'Printer, 'State, 'Residue, 'Result, 'Tuple> /// Type of a formatting expression. diff --git a/src/FSharp.Core/quotations.fs b/src/FSharp.Core/quotations.fs index 18a3f4cae12..4c71bf0d928 100644 --- a/src/FSharp.Core/quotations.fs +++ b/src/FSharp.Core/quotations.fs @@ -92,7 +92,7 @@ module Helpers = | null -> nullArg argName | _ -> () - let getTypesFromParamInfos (infos: ParameterInfo[]) = + let getTypesFromParamInfos (infos: ParameterInfo array) = infos |> Array.map (fun pi -> pi.ParameterType) open Helpers @@ -456,7 +456,7 @@ module Patterns = /// as a computation. type Instantiable<'T> = (int -> Type) -> 'T - type ByteStream(bytes: byte[], initial: int, len: int) = + type ByteStream(bytes: byte array, initial: int, len: int) = let mutable pos = initial let lim = initial + len @@ -970,7 +970,7 @@ module Patterns = if (not (assignableFrom expectedType receivedType)) then invalidArg "receivedType" (String.Format(threeHoleSR, name, expectedType, receivedType)) - let checkArgs (paramInfos: ParameterInfo[]) (args: Expr list) = + let checkArgs (paramInfos: ParameterInfo array) (args: Expr list) = if (paramInfos.Length <> args.Length) then invalidArg "args" (SR.GetString(SR.QincorrectNumArgs)) @@ -1381,7 +1381,7 @@ module Patterns = let typesEqual (tys1: Type list) (tys2: Type list) = (tys1.Length = tys2.Length) && List.forall2 typeEquals tys1 tys2 - let instFormal (typarEnv: Type[]) (ty: Instantiable<'T>) = + let instFormal (typarEnv: Type array) (ty: Instantiable<'T>) = ty (fun i -> typarEnv.[i]) let getGenericArguments (genericType: Type) = @@ -1672,9 +1672,9 @@ module Patterns = type InputState = { is: ByteStream - istrings: string[] + istrings: string array localAssembly: System.Reflection.Assembly - referencedTypeDefs: Type[] + referencedTypeDefs: Type array } let u_byte_as_int st = @@ -1935,7 +1935,7 @@ module Patterns = varn = env.varn + 1 } - let mkTyparSubst (tyargs: Type[]) = + let mkTyparSubst (tyargs: Type array) = let n = tyargs.Length fun idx -> @@ -1944,7 +1944,7 @@ module Patterns = else invalidOp (SR.GetString(SR.QtypeArgumentOutOfRange)) - let envClosed (spliceTypes: Type[]) = + let envClosed (spliceTypes: Type array) = { vars = Map.empty varn = 0 @@ -2256,7 +2256,7 @@ module Patterns = //-------------------------------------------------------------------------- /// Fill the holes in an Expr - let rec fillHolesInRawExpr (l: Expr[]) (E t as e) = + let rec fillHolesInRawExpr (l: Expr array) (E t as e) = match t with | VarTerm _ -> e | LambdaTerm(v, b) -> EA(LambdaTerm(v, fillHolesInRawExpr l b), e.CustomAttributes) @@ -2363,7 +2363,7 @@ module Patterns = resourceName.StartsWith(ReflectedDefinitionsResourceNameBase, StringComparison.Ordinal) /// Get the reflected definition at the given (always generic) instantiation - let tryGetReflectedDefinition (methodBase: MethodBase, tyargs: Type[]) = + let tryGetReflectedDefinition (methodBase: MethodBase, tyargs: Type array) = checkNonNull "methodBase" methodBase let data = @@ -2692,12 +2692,12 @@ type Expr with static member Cast(source: Expr) = cast source - static member Deserialize(qualifyingType: Type, spliceTypes, spliceExprs, bytes: byte[]) = + static member Deserialize(qualifyingType: Type, spliceTypes, spliceExprs, bytes: byte array) = checkNonNull "qualifyingType" qualifyingType checkNonNull "bytes" bytes deserialize (qualifyingType, [||], Array.ofList spliceTypes, Array.ofList spliceExprs, bytes) - static member Deserialize40(qualifyingType: Type, referencedTypes, spliceTypes, spliceExprs, bytes: byte[]) = + static member Deserialize40(qualifyingType: Type, referencedTypes, spliceTypes, spliceExprs, bytes: byte array) = checkNonNull "spliceExprs" spliceExprs checkNonNull "spliceTypes" spliceTypes checkNonNull "referencedTypeDefs" referencedTypes diff --git a/src/FSharp.Core/quotations.fsi b/src/FSharp.Core/quotations.fsi index f3aec29009a..ad69f801996 100644 --- a/src/FSharp.Core/quotations.fsi +++ b/src/FSharp.Core/quotations.fsi @@ -1269,7 +1269,7 @@ type Expr = /// /// The resulting expression. static member Deserialize: - qualifyingType: Type * spliceTypes: Type list * spliceExprs: Expr list * bytes: byte[] -> Expr + qualifyingType: Type * spliceTypes: Type list * spliceExprs: Expr list * bytes: byte array -> Expr /// This function is called automatically when quotation syntax (<@ @>) and other sources of /// quotations are used. @@ -1282,7 +1282,11 @@ type Expr = /// /// The resulting expression. static member Deserialize40: - qualifyingType: Type * referencedTypes: Type[] * spliceTypes: Type[] * spliceExprs: Expr[] * bytes: byte[] -> + qualifyingType: Type * + referencedTypes: Type array * + spliceTypes: Type array * + spliceExprs: Expr array * + bytes: byte array -> Expr /// Permits interactive environments such as F# Interactive @@ -1293,7 +1297,8 @@ type Expr = /// The unique name for the resources being added. /// The serialized resource to register with the environment. /// - static member RegisterReflectedDefinitions: assembly: Assembly * resource: string * serializedValue: byte[] -> unit + static member RegisterReflectedDefinitions: + assembly: Assembly * resource: string * serializedValue: byte array -> unit /// Permits interactive environments such as F# Interactive /// to explicitly register new pickled resources that represent persisted @@ -1305,7 +1310,7 @@ type Expr = /// The serialized resource to register with the environment. /// static member RegisterReflectedDefinitions: - assembly: Assembly * resource: string * serializedValue: byte[] * referencedTypes: Type[] -> unit + assembly: Assembly * resource: string * serializedValue: byte array * referencedTypes: Type array -> unit /// Fetches or creates a new variable with the given name and type from a global pool of shared variables /// indexed by name and type. The type is given by the explicit or inferred type parameter diff --git a/src/FSharp.Core/reflect.fs b/src/FSharp.Core/reflect.fs index df487893df9..500d0b2effc 100644 --- a/src/FSharp.Core/reflect.fs +++ b/src/FSharp.Core/reflect.fs @@ -91,12 +91,12 @@ module internal Impl = expr.Compile() - let compileRecordOrUnionCaseReaderFunc (typ, props: PropertyInfo[]) = + let compileRecordOrUnionCaseReaderFunc (typ, props: PropertyInfo array) = let param = Expression.Parameter(typeof, "param") let typedParam = Expression.Variable typ let expr = - Expression.Lambda>( + Expression.Lambda>( Expression.Block( [ typedParam ], Expression.Assign(typedParam, Expression.Convert(param, typ)), @@ -115,10 +115,10 @@ module internal Impl = let compileRecordConstructorFunc (ctorInfo: ConstructorInfo) = let ctorParams = ctorInfo.GetParameters() - let paramArray = Expression.Parameter(typeof, "paramArray") + let paramArray = Expression.Parameter(typeof, "paramArray") let expr = - Expression.Lambda>( + Expression.Lambda>( Expression.Convert( Expression.New( ctorInfo, @@ -139,10 +139,10 @@ module internal Impl = let compileUnionCaseConstructorFunc (methodInfo: MethodInfo) = let methodParams = methodInfo.GetParameters() - let paramArray = Expression.Parameter(typeof, "param") + let paramArray = Expression.Parameter(typeof, "param") let expr = - Expression.Lambda>( + Expression.Lambda>( Expression.Convert( Expression.Call( methodInfo, @@ -192,10 +192,10 @@ module internal Impl = ] ) - let elements = Expression.Parameter(typeof, "elements") + let elements = Expression.Parameter(typeof, "elements") let expr = - Expression.Lambda>( + Expression.Lambda>( Expression.Convert(constituentTuple typ elements 0, typeof), elements ) @@ -208,10 +208,10 @@ module internal Impl = let elements = match getTupleElementAccessors typ with // typ is a struct tuple and its elements are accessed via fields - | Choice1Of2(fi: FieldInfo[]) -> + | Choice1Of2(fi: FieldInfo array) -> fi |> Array.map (fun fi -> Expression.Field(tuple, fi), fi.FieldType) // typ is a class tuple and its elements are accessed via properties - | Choice2Of2(pi: PropertyInfo[]) -> + | Choice2Of2(pi: PropertyInfo array) -> pi |> Array.map (fun pi -> Expression.Property(tuple, pi), pi.PropertyType) for index, (element, elementType) in elements |> Array.indexed do @@ -235,7 +235,7 @@ module internal Impl = } let param = Expression.Parameter(typeof, "outerTuple") - let outputArray = Expression.Variable(typeof, "output") + let outputArray = Expression.Variable(typeof, "output") let rec outputLength tupleEncField (typ: Type) = let genericArgs = typ.GetGenericArguments() @@ -246,7 +246,7 @@ module internal Impl = genericArgs.Length let expr = - Expression.Lambda>( + Expression.Lambda>( Expression.Block( [ outputArray ], [ @@ -266,7 +266,7 @@ module internal Impl = //----------------------------------------------------------------- // ATTRIBUTE DECOMPILATION - let tryFindCompilationMappingAttribute (attrs: obj[]) = + let tryFindCompilationMappingAttribute (attrs: obj array) = match attrs with | null | [||] -> None @@ -275,7 +275,7 @@ module internal Impl = Some(a.SourceConstructFlags, a.SequenceNumber, a.VariantNumber) | _ -> invalidOp (SR.GetString(SR.multipleCompilationMappings)) - let findCompilationMappingAttribute (attrs: obj[]) = + let findCompilationMappingAttribute (attrs: obj array) = match tryFindCompilationMappingAttribute attrs with | None -> failwith "no compilation mapping attribute" | Some a -> a @@ -688,10 +688,10 @@ module internal Impl = |] let private dictionaryLock = obj () - let private refTupleTypes = Dictionary() - let private valueTupleTypes = Dictionary() + let private refTupleTypes = Dictionary() + let private valueTupleTypes = Dictionary() - let rec mkTupleType isStruct (asm: Assembly) (tys: Type[]) = + let rec mkTupleType isStruct (asm: Assembly) (tys: Type array) = let table = let makeIt n = let tupleFullName n = @@ -777,7 +777,7 @@ module internal Impl = [] let lastRegularTupIndex = 6 //nestedTupIndex - 1 (wait for arithmetic in constants) - let rec mkTupleTypeNetStandard (tupTyTbl: Type[]) (tys: Type[]) = + let rec mkTupleTypeNetStandard (tupTyTbl: Type array) (tys: Type array) = let tblIdx = tys.Length - 1 assert (tblIdx >= 0) assert (nestedTupIndex = tupTyTbl.Length - 1) @@ -804,12 +804,12 @@ module internal Impl = else tyargs - let orderTupleProperties (props: PropertyInfo[]) = - // The PropertyInfo[] may not come back in order, so ensure ordering here. + let orderTupleProperties (props: PropertyInfo array) = + // The PropertyInfo array may not come back in order, so ensure ordering here. props |> Array.sortBy (fun p -> p.Name) // alphabetic works because there is max. 8 of them - let orderTupleFields (fields: FieldInfo[]) = - // The FieldInfo[] may not come back in order, so ensure ordering here. + let orderTupleFields (fields: FieldInfo array) = + // The FieldInfo array may not come back in order, so ensure ordering here. fields |> Array.sortBy (fun fi -> fi.Name) // alphabetic works because there is max. 8 of them let getTupleConstructorMethod (typ: Type) = @@ -845,7 +845,7 @@ module internal Impl = let getTupleCtor (typ: Type) = let ctor = getTupleConstructorMethod typ - (fun (args: obj[]) -> + (fun (args: obj array) -> ctor.Invoke(BindingFlags.InvokeMethod ||| BindingFlags.Instance ||| BindingFlags.Public, null, args, null)) let getTupleElementAccessors (typ: Type) = @@ -886,7 +886,7 @@ module internal Impl = let tyBenc = etys.[tupleEncField] let maker2 = getTupleConstructor tyBenc - (fun (args: obj[]) -> + (fun (args: obj array) -> let encVal = maker2 args.[tupleEncField..] maker1 (Array.append args.[0 .. tupleEncField - 1] [| encVal |])) @@ -1005,7 +1005,7 @@ module internal Impl = let getRecordConstructor (typ: Type, bindingFlags) = let ctor = getRecordConstructorMethod (typ, bindingFlags) - (fun (args: obj[]) -> + (fun (args: obj array) -> ctor.Invoke(BindingFlags.InvokeMethod ||| BindingFlags.Instance ||| bindingFlags, null, args, null)) let getRecordConstructorCompiled (typ: Type, bindingFlags) = @@ -1155,7 +1155,7 @@ type FSharpType = checkNonNull "range" range func.MakeGenericType [| domain; range |] - static member MakeTupleType(types: Type[]) = + static member MakeTupleType(types: Type array) = checkNonNull "types" types if types.Length = 0 then @@ -1166,7 +1166,7 @@ type FSharpType = mkTupleTypeNetStandard refTupleTypesNetStandard types - static member MakeTupleType(asm: Assembly, types: Type[]) = + static member MakeTupleType(asm: Assembly, types: Type array) = checkNonNull "types" types if @@ -1179,7 +1179,7 @@ type FSharpType = TupleFromSpecifiedAssembly.mkTupleType false asm types - static member MakeStructTupleType(asm: Assembly, types: Type[]) = + static member MakeStructTupleType(asm: Assembly, types: Type array) = checkNonNull "types" types if @@ -1192,7 +1192,7 @@ type FSharpType = TupleFromSpecifiedAssembly.mkTupleType true asm types - static member MakeStructTupleType(types: Type[]) = + static member MakeStructTupleType(types: Type array) = checkNonNull "types" types if types.Length = 0 then @@ -1278,7 +1278,7 @@ type FSharpValue = checkNonNull "info" info compilePropGetterFunc(info).Invoke - static member PreComputeRecordReader(recordType: Type, ?bindingFlags) : (obj -> obj[]) = + static member PreComputeRecordReader(recordType: Type, ?bindingFlags) : (obj -> obj array) = let bindingFlags = defaultArg bindingFlags BindingFlags.Public checkRecordType ("recordType", recordType, bindingFlags) getRecordReaderCompiled (recordType, bindingFlags) @@ -1308,7 +1308,7 @@ type FSharpValue = let (f: (obj -> obj) -> obj) = downcast o f implementation - static member MakeTuple(tupleElements: obj[], tupleType: Type) = + static member MakeTuple(tupleElements: obj array, tupleType: Type) = checkNonNull "tupleElements" tupleElements checkTupleType ("tupleType", tupleType) getTupleConstructor tupleType tupleElements @@ -1341,7 +1341,7 @@ type FSharpValue = fields.[index] - static member PreComputeTupleReader(tupleType: Type) : (obj -> obj[]) = + static member PreComputeTupleReader(tupleType: Type) : (obj -> obj array) = checkTupleType ("tupleType", tupleType) (compileTupleReader tupleEncField getTupleElementAccessors tupleType).Invoke @@ -1359,7 +1359,7 @@ type FSharpValue = checkTupleType ("tupleType", tupleType) getTupleConstructorInfo tupleType - static member MakeUnion(unionCase: UnionCaseInfo, args: obj[], ?bindingFlags) = + static member MakeUnion(unionCase: UnionCaseInfo, args: obj array, ?bindingFlags) = let bindingFlags = defaultArg bindingFlags BindingFlags.Public checkNonNull "unionCase" unionCase getUnionCaseConstructor (unionCase.DeclaringType, unionCase.Tag, bindingFlags) args @@ -1409,7 +1409,7 @@ type FSharpValue = checkUnionType (unionType, bindingFlags) getUnionTagMemberInfo (unionType, bindingFlags) - static member PreComputeUnionReader(unionCase: UnionCaseInfo, ?bindingFlags) : (obj -> obj[]) = + static member PreComputeUnionReader(unionCase: UnionCaseInfo, ?bindingFlags) : (obj -> obj array) = let bindingFlags = defaultArg bindingFlags BindingFlags.Public checkNonNull "unionCase" unionCase let typ = unionCase.DeclaringType @@ -1460,7 +1460,11 @@ module FSharpReflectionExtensions = let bindingFlags = getBindingFlags allowAccessToPrivateRepresentation FSharpValue.GetRecordFields(record, bindingFlags) - static member PreComputeRecordReader(recordType: Type, ?allowAccessToPrivateRepresentation) : (obj -> obj[]) = + static member PreComputeRecordReader + ( + recordType: Type, + ?allowAccessToPrivateRepresentation + ) : (obj -> obj array) = let bindingFlags = getBindingFlags allowAccessToPrivateRepresentation FSharpValue.PreComputeRecordReader(recordType, bindingFlags) @@ -1472,7 +1476,7 @@ module FSharpReflectionExtensions = let bindingFlags = getBindingFlags allowAccessToPrivateRepresentation FSharpValue.PreComputeRecordConstructorInfo(recordType, bindingFlags) - static member MakeUnion(unionCase: UnionCaseInfo, args: obj[], ?allowAccessToPrivateRepresentation) = + static member MakeUnion(unionCase: UnionCaseInfo, args: obj array, ?allowAccessToPrivateRepresentation) = let bindingFlags = getBindingFlags allowAccessToPrivateRepresentation FSharpValue.MakeUnion(unionCase, args, bindingFlags) @@ -1500,7 +1504,7 @@ module FSharpReflectionExtensions = ( unionCase: UnionCaseInfo, ?allowAccessToPrivateRepresentation - ) : (obj -> obj[]) = + ) : (obj -> obj array) = let bindingFlags = getBindingFlags allowAccessToPrivateRepresentation FSharpValue.PreComputeUnionReader(unionCase, bindingFlags) diff --git a/src/FSharp.Core/reflect.fsi b/src/FSharp.Core/reflect.fsi index 5d69af7f9a3..9aa76f62a69 100644 --- a/src/FSharp.Core/reflect.fsi +++ b/src/FSharp.Core/reflect.fsi @@ -82,7 +82,7 @@ type UnionCaseInfo = /// VariantNumber = 0;}|]|] /// /// - member GetCustomAttributes: unit -> obj[] + member GetCustomAttributes: unit -> obj array /// Returns the custom attributes associated with the case matching the given attribute type. /// The type of attributes to return. @@ -111,7 +111,7 @@ type UnionCaseInfo = /// TypeId = FSI_0147+Signal;}|]|] /// /// - member GetCustomAttributes: attributeType: Type -> obj[] + member GetCustomAttributes: attributeType: Type -> obj array /// Returns the custom attributes data associated with the case. /// An list of custom attribute data items. @@ -176,7 +176,7 @@ type UnionCaseInfo = /// [|("width", "Double"); ("Item2", "Double"); ("height", "Double")|]|] /// /// - member GetFields: unit -> PropertyInfo[] + member GetFields: unit -> PropertyInfo array /// The integer tag for the case. /// @@ -243,7 +243,7 @@ type FSharpValue = /// static member MakeRecord: [] recordType: Type * - values: obj[] * + values: obj array * ?bindingFlags: BindingFlags -> obj @@ -258,7 +258,7 @@ type FSharpValue = /// The array of fields from the record. /// /// - static member GetRecordFields: record: obj * ?bindingFlags: BindingFlags -> obj[] + static member GetRecordFields: record: obj * ?bindingFlags: BindingFlags -> obj array /// Precompute a function for reading all the fields from a record. The fields are returned in the /// same order as the fields reported by a call to Microsoft.FSharp.Reflection.Type.GetInfo for @@ -282,7 +282,7 @@ type FSharpValue = static member PreComputeRecordReader: [] recordType: Type * ?bindingFlags: BindingFlags -> - (obj -> obj[]) + (obj -> obj array) /// Precompute a function for constructing a record value. /// @@ -300,7 +300,7 @@ type FSharpValue = static member PreComputeRecordConstructor: [] recordType: Type * ?bindingFlags: BindingFlags -> - (obj[] -> obj) + (obj array -> obj) /// Get a ConstructorInfo for a record type /// @@ -324,7 +324,7 @@ type FSharpValue = /// The constructed union case. /// /// - static member MakeUnion: unionCase: UnionCaseInfo * args: obj[] * ?bindingFlags: BindingFlags -> obj + static member MakeUnion: unionCase: UnionCaseInfo * args: obj array * ?bindingFlags: BindingFlags -> obj /// Identify the union case and its fields for an object /// @@ -346,7 +346,7 @@ type FSharpValue = value: obj * [] unionType: Type * ?bindingFlags: BindingFlags -> - UnionCaseInfo * obj[] + UnionCaseInfo * obj array /// Assumes the given type is a union type. /// If not, is raised during pre-computation. @@ -387,7 +387,7 @@ type FSharpValue = /// A function to for reading the fields of the given union case. /// /// - static member PreComputeUnionReader: unionCase: UnionCaseInfo * ?bindingFlags: BindingFlags -> (obj -> obj[]) + static member PreComputeUnionReader: unionCase: UnionCaseInfo * ?bindingFlags: BindingFlags -> (obj -> obj array) /// Precompute a function for constructing a discriminated union value for a particular union case. /// @@ -397,7 +397,8 @@ type FSharpValue = /// A function for constructing values of the given union case. /// /// - static member PreComputeUnionConstructor: unionCase: UnionCaseInfo * ?bindingFlags: BindingFlags -> (obj[] -> obj) + static member PreComputeUnionConstructor: + unionCase: UnionCaseInfo * ?bindingFlags: BindingFlags -> (obj array -> obj) /// A method that constructs objects of the given case /// @@ -421,7 +422,7 @@ type FSharpValue = /// The fields from the given exception. /// /// - static member GetExceptionFields: exn: obj * ?bindingFlags: BindingFlags -> obj[] + static member GetExceptionFields: exn: obj * ?bindingFlags: BindingFlags -> obj array /// Creates an instance of a tuple type /// @@ -435,7 +436,7 @@ type FSharpValue = /// An instance of the tuple type with the given elements. /// /// - static member MakeTuple: tupleElements: obj[] * tupleType: Type -> obj + static member MakeTuple: tupleElements: obj array * tupleType: Type -> obj /// Reads a field from a tuple value. /// @@ -460,7 +461,7 @@ type FSharpValue = /// An array of the fields from the given tuple. /// /// - static member GetTupleFields: tuple: obj -> obj[] + static member GetTupleFields: tuple: obj -> obj array /// Precompute a function for reading the values of a particular tuple type /// @@ -475,7 +476,7 @@ type FSharpValue = /// /// static member PreComputeTupleReader: - [] tupleType: Type -> (obj -> obj[]) + [] tupleType: Type -> (obj -> obj array) /// Gets information that indicates how to read a field of a tuple /// @@ -502,7 +503,7 @@ type FSharpValue = /// /// static member PreComputeTupleConstructor: - [] tupleType: Type -> (obj[] -> obj) + [] tupleType: Type -> (obj array -> obj) /// Gets a method that constructs objects of the given tuple type. /// For small tuples, no additional type will be returned. @@ -554,7 +555,7 @@ type FSharpType = static member GetRecordFields: [] recordType: Type * ?bindingFlags: BindingFlags -> - PropertyInfo[] + PropertyInfo array /// Gets the cases of a union type. /// @@ -570,7 +571,7 @@ type FSharpType = /// static member GetUnionCases: [] unionType: Type * ?bindingFlags: BindingFlags -> - UnionCaseInfo[] + UnionCaseInfo array /// Return true if the typ is a representation of an F# record type /// @@ -611,7 +612,7 @@ type FSharpType = static member GetExceptionFields: [] exceptionType: Type * ?bindingFlags: BindingFlags -> - PropertyInfo[] + PropertyInfo array /// Returns true if the typ is a representation of an F# exception declaration /// @@ -646,7 +647,7 @@ type FSharpType = /// The type representing the tuple containing the input elements. /// /// - static member MakeTupleType: types: Type[] -> Type + static member MakeTupleType: types: Type array -> Type /// Returns a representing an F# tuple type with the given element types /// @@ -656,7 +657,7 @@ type FSharpType = /// The type representing the tuple containing the input elements. /// /// - static member MakeTupleType: asm: Assembly * types: Type[] -> Type + static member MakeTupleType: asm: Assembly * types: Type array -> Type /// Returns a representing an F# struct tuple type with the given element types /// @@ -666,7 +667,7 @@ type FSharpType = /// The type representing the struct tuple containing the input elements. /// /// - static member MakeStructTupleType: asm: Assembly * types: Type[] -> Type + static member MakeStructTupleType: asm: Assembly * types: Type array -> Type /// Returns a representing an F# struct tuple type with the given element types /// @@ -675,7 +676,7 @@ type FSharpType = /// The type representing the struct tuple containing the input elements. /// /// - static member MakeStructTupleType: types: Type[] -> Type + static member MakeStructTupleType: types: Type array -> Type /// Return true if the typ is a representation of an F# tuple type /// @@ -712,7 +713,7 @@ type FSharpType = /// /// static member GetTupleElements: - [] tupleType: Type -> Type[] + [] tupleType: Type -> Type array /// Gets the domain and range types from an F# function type or from the runtime type of a closure implementing an F# type /// @@ -744,7 +745,7 @@ module FSharpReflectionExtensions = /// static member MakeRecord: [] recordType: Type * - values: obj[] * + values: obj array * ?allowAccessToPrivateRepresentation: bool -> obj @@ -763,7 +764,7 @@ module FSharpReflectionExtensions = static member GetRecordFields: [] record: obj * ?allowAccessToPrivateRepresentation: bool -> - obj[] + obj array /// Precompute a function for reading all the fields from a record. The fields are returned in the /// same order as the fields reported by a call to Microsoft.FSharp.Reflection.Type.GetInfo for @@ -787,7 +788,7 @@ module FSharpReflectionExtensions = static member PreComputeRecordReader: [] recordType: Type * ?allowAccessToPrivateRepresentation: bool -> - (obj -> obj[]) + (obj -> obj array) /// Precompute a function for constructing a record value. /// @@ -805,7 +806,7 @@ module FSharpReflectionExtensions = static member PreComputeRecordConstructor: [] recordType: Type * ?allowAccessToPrivateRepresentation: bool -> - (obj[] -> obj) + (obj array -> obj) /// Get a ConstructorInfo for a record type /// @@ -830,7 +831,7 @@ module FSharpReflectionExtensions = /// /// static member MakeUnion: - unionCase: UnionCaseInfo * args: obj[] * ?allowAccessToPrivateRepresentation: bool -> obj + unionCase: UnionCaseInfo * args: obj array * ?allowAccessToPrivateRepresentation: bool -> obj /// Identify the union case and its fields for an object /// @@ -853,7 +854,7 @@ module FSharpReflectionExtensions = value: obj * [] unionType: Type * ?allowAccessToPrivateRepresentation: bool -> - UnionCaseInfo * obj[] + UnionCaseInfo * obj array /// Assumes the given type is a union type. /// If not, is raised during pre-computation. @@ -897,7 +898,7 @@ module FSharpReflectionExtensions = /// /// static member PreComputeUnionReader: - unionCase: UnionCaseInfo * ?allowAccessToPrivateRepresentation: bool -> (obj -> obj[]) + unionCase: UnionCaseInfo * ?allowAccessToPrivateRepresentation: bool -> (obj -> obj array) /// Precompute a function for constructing a discriminated union value for a particular union case. /// @@ -908,7 +909,7 @@ module FSharpReflectionExtensions = /// /// static member PreComputeUnionConstructor: - unionCase: UnionCaseInfo * ?allowAccessToPrivateRepresentation: bool -> (obj[] -> obj) + unionCase: UnionCaseInfo * ?allowAccessToPrivateRepresentation: bool -> (obj array -> obj) /// A method that constructs objects of the given case /// @@ -933,7 +934,7 @@ module FSharpReflectionExtensions = /// The fields from the given exception. /// /// - static member GetExceptionFields: exn: obj * ?allowAccessToPrivateRepresentation: bool -> obj[] + static member GetExceptionFields: exn: obj * ?allowAccessToPrivateRepresentation: bool -> obj array type FSharpType with @@ -950,7 +951,7 @@ module FSharpReflectionExtensions = static member GetRecordFields: [] recordType: Type * ?allowAccessToPrivateRepresentation: bool -> - PropertyInfo[] + PropertyInfo array /// Gets the cases of a union type. /// @@ -967,7 +968,7 @@ module FSharpReflectionExtensions = static member GetUnionCases: [] unionType: Type * ?allowAccessToPrivateRepresentation: bool -> - UnionCaseInfo[] + UnionCaseInfo array /// Return true if the typ is a representation of an F# record type /// @@ -1010,7 +1011,7 @@ module FSharpReflectionExtensions = static member GetExceptionFields: [] exceptionType: Type * ?allowAccessToPrivateRepresentation: bool -> - PropertyInfo[] + PropertyInfo array /// Returns true if the exceptionType is a representation of an F# exception declaration /// diff --git a/src/FSharp.Core/result.fsi b/src/FSharp.Core/result.fsi index a5b7a5cb37a..db9a2aa2a42 100644 --- a/src/FSharp.Core/result.fsi +++ b/src/FSharp.Core/result.fsi @@ -166,7 +166,7 @@ module Result = val inline fold<'T, 'Error, 'State> : folder: ('State -> 'T -> 'State) -> state: 'State -> result: Result<'T, 'Error> -> 'State - /// fold f inp s evaluates to match inp with Error _ -> s | Ok x -> f x s. + /// foldBack f inp s evaluates to match inp with Error _ -> s | Ok x -> f x s. /// /// A function to update the state data when given a value from an result. /// The input result. @@ -266,7 +266,7 @@ module Result = /// /// [] - val inline toArray: result: Result<'T, 'Error> -> 'T[] + val inline toArray: result: Result<'T, 'Error> -> 'T array /// Convert the result to a list of length 0 or 1. /// diff --git a/src/FSharp.Core/resumable.fs b/src/FSharp.Core/resumable.fs index e63e79f92dd..24131ea155f 100644 --- a/src/FSharp.Core/resumable.fs +++ b/src/FSharp.Core/resumable.fs @@ -115,6 +115,7 @@ module StateMachineHelpers = "__stateMachine should always be guarded by __useResumableCode and only used in valid state machine implementations" module ResumableCode = + open System.Runtime.ExceptionServices let inline GetResumptionFunc (sm: byref>) = sm.ResumptionDynamicInfo.ResumptionFunc @@ -294,7 +295,10 @@ module ResumableCode = // reraise at the end of the finally block match savedExn with | None -> true - | Some exn -> raise exn + | Some exn -> + // This should preserve initial location for the failure (file + line, given they're available). + ExceptionDispatchInfo.Capture(exn).Throw() + true else let rf = GetResumptionFunc &sm @@ -384,7 +388,7 @@ module ResumableCode = if __stack_fin then match savedExn with | None -> () - | Some exn -> raise exn + | Some exn -> ExceptionDispatchInfo.Capture(exn).Throw() __stack_fin //-- RESUMABLE CODE END diff --git a/src/FSharp.Core/seq.fs b/src/FSharp.Core/seq.fs index 13770d726ca..bfe050f9f7c 100644 --- a/src/FSharp.Core/seq.fs +++ b/src/FSharp.Core/seq.fs @@ -873,7 +873,7 @@ module Seq = checkNonNull "source" source match source with - | :? ('T[]) as a -> a.Length = 0 + | :? ('T array) as a -> a.Length = 0 | :? ('T list) as a -> a.IsEmpty | :? ICollection<'T> as a -> a.Count = 0 | _ -> @@ -890,7 +890,7 @@ module Seq = checkNonNull "source" source match source with - | :? ('T[]) as a -> a.Length + | :? ('T array) as a -> a.Length | :? ('T list) as a -> a.Length | :? ICollection<'T> as a -> a.Count | _ -> @@ -1014,7 +1014,7 @@ module Seq = checkNonNull "source" source match source with - | :? ('T[]) as res -> (res.Clone() :?> 'T[]) + | :? ('T array) as res -> (res.Clone() :?> 'T array) | :? ('T list) as res -> List.toArray res | :? ICollection<'T> as res -> // Directly create an array and copy ourselves. @@ -1037,7 +1037,7 @@ module Seq = else [||] - let foldArraySubRight (f: OptimizedClosures.FSharpFunc<'T, _, _>) (arr: 'T[]) start fin acc = + let foldArraySubRight (f: OptimizedClosures.FSharpFunc<'T, _, _>) (arr: 'T array) start fin acc = let mutable state = acc for i = fin downto start do @@ -1181,7 +1181,7 @@ module Seq = checkNonNull "source" source source |> toArray |> Array.findIndexBack predicate - // windowed : int -> seq<'T> -> seq<'T[]> + // windowed : int -> seq<'T> -> seq<'T array> [] let windowed windowSize (source: seq<_>) = checkNonNull "source" source diff --git a/src/FSharp.Core/seq.fsi b/src/FSharp.Core/seq.fsi index 9ce69ed5ce4..4bdf2a54d6d 100644 --- a/src/FSharp.Core/seq.fsi +++ b/src/FSharp.Core/seq.fsi @@ -249,7 +249,7 @@ module Seq = /// Throws ArgumentException /// [] - val chunkBySize: chunkSize: int -> source: seq<'T> -> seq<'T[]> + val chunkBySize: chunkSize: int -> source: seq<'T> -> seq<'T array> /// Applies the given function to each element of the sequence and concatenates all the /// results. @@ -530,7 +530,7 @@ module Seq = /// Throws ArgumentException /// [] - val splitInto: count: int -> source: seq<'T> -> seq<'T[]> + val splitInto: count: int -> source: seq<'T> -> seq<'T array> /// Creates an empty sequence. /// @@ -1833,7 +1833,7 @@ module Seq = /// Evaluates to a sequence yielding the same results as seq { 1; 2; 5 }. /// [] - val ofArray: source: 'T[] -> seq<'T> + val ofArray: source: 'T array -> seq<'T> /// Views the given list as a sequence. /// @@ -1955,7 +1955,7 @@ module Seq = /// /// let readonlyView = input |> Seq.readonly /// - /// (readonlyView :?> int[]).[1] <- 4 + /// (readonlyView :?> int array).[1] <- 4 /// /// Throws an InvalidCastException. /// @@ -2474,7 +2474,7 @@ module Seq = /// Evaluates to [| 1; 2; 5 |]. /// [] - val toArray: source: seq<'T> -> 'T[] + val toArray: source: seq<'T> -> 'T array /// Builds a list from the given collection. /// @@ -2792,7 +2792,7 @@ module Seq = /// Evaluates to a sequence of arrays yielding the results seq { [| 1; 2; 3 |]; [| 2; 3; 4 |]; [| 3; 4; 5 |] } /// [] - val windowed: windowSize: int -> source: seq<'T> -> seq<'T[]> + val windowed: windowSize: int -> source: seq<'T> -> seq<'T array> /// Combines the two sequences into a sequence of pairs. The two sequences need not have equal lengths: /// when one sequence is exhausted any remaining elements in the other diff --git a/src/FSharp.Core/seqcore.fs b/src/FSharp.Core/seqcore.fs index 2ec6f60815a..187ed402362 100644 --- a/src/FSharp.Core/seqcore.fs +++ b/src/FSharp.Core/seqcore.fs @@ -553,7 +553,7 @@ type ListCollector<'T> = member this.AddMany (values: seq<'T>) = // cook a faster iterator for lists and arrays match values with - | :? ('T[]) as valuesAsArray -> + | :? ('T array) as valuesAsArray -> for v in valuesAsArray do this.Add v | :? ('T list) as valuesAsList -> @@ -631,7 +631,7 @@ type ArrayCollector<'T> = else // cook a faster iterator for lists and arrays match values with - | :? ('T[]) as valuesAsArray -> + | :? ('T array) as valuesAsArray -> for v in valuesAsArray do this.Add v | :? ('T list) as valuesAsList -> diff --git a/src/FSharp.Core/seqcore.fsi b/src/FSharp.Core/seqcore.fsi index 1522522000b..e58e1f6ce68 100644 --- a/src/FSharp.Core/seqcore.fsi +++ b/src/FSharp.Core/seqcore.fsi @@ -205,7 +205,7 @@ type ArrayCollector<'T> = member AddMany: values: seq<'T> -> unit /// Add multiple elements to the collector and return the resulting array - member AddManyAndClose: values: seq<'T> -> 'T[] + member AddManyAndClose: values: seq<'T> -> 'T array /// Return the resulting list - member Close: unit -> 'T[] + member Close: unit -> 'T array diff --git a/src/FSharp.Core/set.fs b/src/FSharp.Core/set.fs index aaed3e37a41..b47bef257c1 100644 --- a/src/FSharp.Core/set.fs +++ b/src/FSharp.Core/set.fs @@ -669,7 +669,7 @@ module internal SetTree = loop t [] - let copyToArray s (arr: _[]) i = + let copyToArray s (arr: _ array) i = let mutable j = i iter diff --git a/src/FSharp.Core/set.fsi b/src/FSharp.Core/set.fsi index f1c2fd291c2..58615cedaa9 100644 --- a/src/FSharp.Core/set.fsi +++ b/src/FSharp.Core/set.fsi @@ -752,7 +752,7 @@ module Set = /// The sample evaluates to the following output: The set is set [(1, 2, 3)] and type is "FSharpSet`1" /// [] - val ofArray: array: 'T[] -> Set<'T> + val ofArray: array: 'T array -> Set<'T> /// Builds an array that contains the elements of the set in order. /// @@ -766,10 +766,10 @@ module Set = /// let array = Set.toArray set /// printfn$ "The set is {set} and type is {array.GetType().Name}" /// - /// The sample evaluates to the following output: The set is [|1; 2; 3|] and type is System.Int32[] + /// The sample evaluates to the following output: The set is [|1; 2; 3|] and type is System.Int32 array /// [] - val toArray: set: Set<'T> -> 'T[] + val toArray: set: Set<'T> -> 'T array /// Returns an ordered view of the collection as an enumerable object. /// diff --git a/src/FSharp.Core/string.fs b/src/FSharp.Core/string.fs index 42f86f75079..d716b793db1 100644 --- a/src/FSharp.Core/string.fs +++ b/src/FSharp.Core/string.fs @@ -26,7 +26,7 @@ module String = [] let concat sep (strings: seq) = - let concatArray sep (strings: string[]) = + let concatArray sep (strings: string array) = match length sep with | 0 -> String.Concat strings // following line should be used when this overload becomes part of .NET Standard (it's only in .NET Core) @@ -34,7 +34,7 @@ module String = | _ -> String.Join(sep, strings, 0, strings.Length) match strings with - | :? (string[]) as arr -> concatArray sep arr + | :? (string array) as arr -> concatArray sep arr | :? (string list) as lst -> lst |> List.toArray |> concatArray sep diff --git a/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.fsproj b/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.fsproj index f7560b70738..a427f7006dd 100644 --- a/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.fsproj +++ b/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.fsproj @@ -9,13 +9,6 @@ .NET Core compatible version of the F# compiler fsc.exe. /blob/main/release-notes.md#FSharp-Tools-$(FSProductVersionReleaseNotesVersion) true - - $(NoWarn);NU1505 diff --git a/src/fsc/fsc.targets b/src/fsc/fsc.targets index 47d7ea87264..2973feb613e 100644 --- a/src/fsc/fsc.targets +++ b/src/fsc/fsc.targets @@ -4,14 +4,6 @@ Exe - - $(NoWarn);NU1505 - $(NoWarn);44 $(NoWarn);75 true diff --git a/src/fsi/fsi.targets b/src/fsi/fsi.targets index 4e8c6a6cbc3..2f38a20ecc3 100644 --- a/src/fsi/fsi.targets +++ b/src/fsi/fsi.targets @@ -4,13 +4,6 @@ Exe - - $(NoWarn);NU1505 $(NoWarn);44 true $(OtherFlags) --warnon:1182 diff --git a/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj b/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj index cb02b7e0fd6..90842baa584 100644 --- a/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj @@ -5,7 +5,6 @@ net8.0 preview true - true diff --git a/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj b/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj index d36faf2c0df..7fd0dc7091c 100644 --- a/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj @@ -5,7 +5,6 @@ net8.0 preview true - true false --standalone diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1 index 8d2d17adef2..373cd534ce2 100644 --- a/tests/AheadOfTime/Trimming/check.ps1 +++ b/tests/AheadOfTime/Trimming/check.ps1 @@ -40,7 +40,7 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) { # error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher. # Check net7.0 trimmed assemblies -CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len 288768 +CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len 288256 # Check net7.0 trimmed assemblies CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net8.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 8822272 diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncLock.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncLock.fs new file mode 100644 index 00000000000..ef4b69a3910 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncLock.fs @@ -0,0 +1,26 @@ +module CompilerService.AsyncLock + +open Internal.Utilities.Collections + +open Xunit +open System.Threading.Tasks + + +[] +let ``Async lock works`` () = + task { + use lock = new AsyncLock() + + let mutable x = 0 + + let job () = task { + let y = x + do! Task.Delay(10) + x <- y + 1 + } + + let jobs = [ for _ in 1..100 -> lock.Do job ] + let! _ = Task.WhenAll(jobs) + + Assert.Equal(100, x) + } \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs new file mode 100644 index 00000000000..71dbb5c957f --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs @@ -0,0 +1,542 @@ +module CompilerService.AsyncMemoize + +open System +open System.Threading +open Xunit +open Internal.Utilities.Collections +open System.Threading.Tasks +open System.Diagnostics +open System.Collections.Concurrent +open FSharp.Compiler.DiagnosticsLogger +open FSharp.Compiler.Diagnostics +open FSharp.Compiler.BuildGraph + + +let timeout = TimeSpan.FromSeconds 10 + +let waitFor (mre: ManualResetEvent) = + if not <| mre.WaitOne timeout then + failwith "waitFor timed out" + + +let rec internal spinFor (duration: TimeSpan) = + node { + let sw = Stopwatch.StartNew() + do! Async.Sleep 10 |> NodeCode.AwaitAsync + let remaining = duration - sw.Elapsed + if remaining > TimeSpan.Zero then + return! spinFor remaining + } + + +[] +let ``Basics``() = + + let computation key = node { + do! Async.Sleep 1 |> NodeCode.AwaitAsync + return key * 2 + } + + let eventLog = ConcurrentBag() + + let memoize = AsyncMemoize() + memoize.OnEvent(fun (e, (_label, k, _version)) -> eventLog.Add (e, k)) + + let result = + seq { + memoize.Get'(5, computation 5) + memoize.Get'(5, computation 5) + memoize.Get'(2, computation 2) + memoize.Get'(5, computation 5) + memoize.Get'(3, computation 3) + memoize.Get'(2, computation 2) + } + |> NodeCode.Parallel + |> NodeCode.RunImmediateWithoutCancellation + + let expected = [| 10; 10; 4; 10; 6; 4|] + + Assert.Equal(expected, result) + + let groups = eventLog |> Seq.groupBy snd |> Seq.toList + Assert.Equal(3, groups.Length) + for key, events in groups do + Assert.Equal>(Set [ Started, key; Finished, key ], Set events) + +[] +let ``We can cancel a job`` () = + task { + + let jobStarted = new ManualResetEvent(false) + + let jobCanceled = new ManualResetEvent(false) + + let computation action = node { + action() |> ignore + do! spinFor timeout + failwith "Should be canceled before it gets here" + } + + let eventLog = ConcurrentQueue() + let memoize = AsyncMemoize() + memoize.OnEvent(fun (e, (_label, k, _version)) -> + eventLog.Enqueue (e, k) + if e = Canceled then + jobCanceled.Set() |> ignore + ) + + use cts1 = new CancellationTokenSource() + use cts2 = new CancellationTokenSource() + use cts3 = new CancellationTokenSource() + + let key = 1 + + let _task1 = NodeCode.StartAsTask_ForTesting( memoize.Get'(key, computation jobStarted.Set), ct = cts1.Token) + + waitFor jobStarted + jobStarted.Reset() |> ignore + + let _task2 = NodeCode.StartAsTask_ForTesting( memoize.Get'(key, computation ignore), ct = cts2.Token) + let _task3 = NodeCode.StartAsTask_ForTesting( memoize.Get'(key, computation ignore), ct = cts3.Token) + + cts1.Cancel() + cts2.Cancel() + + waitFor jobStarted + + cts3.Cancel() + + waitFor jobCanceled + + Assert.Equal<(JobEvent * int) array>([| Started, key; Started, key; Canceled, key |], eventLog |> Seq.toArray ) + } + +[] +let ``Job is restarted if first requestor cancels`` () = + task { + let jobStarted = new ManualResetEvent(false) + + let jobCanComplete = new ManualResetEvent(false) + + let computation key = node { + jobStarted.Set() |> ignore + waitFor jobCanComplete + return key * 2 + } + + let eventLog = ConcurrentStack() + let memoize = AsyncMemoize() + memoize.OnEvent(fun (e, (_, k, _version)) -> eventLog.Push (e, k)) + + use cts1 = new CancellationTokenSource() + use cts2 = new CancellationTokenSource() + use cts3 = new CancellationTokenSource() + + let key = 1 + + let _task1 = NodeCode.StartAsTask_ForTesting( memoize.Get'(key, computation key), ct = cts1.Token) + + waitFor jobStarted + jobStarted.Reset() |> ignore + + let _task2 = NodeCode.StartAsTask_ForTesting( memoize.Get'(key, computation key), ct = cts2.Token) + let _task3 = NodeCode.StartAsTask_ForTesting( memoize.Get'(key, computation key), ct = cts3.Token) + + cts1.Cancel() + + waitFor jobStarted + + cts3.Cancel() + + jobCanComplete.Set() |> ignore + + let! result = _task2 + Assert.Equal(2, result) + + let orderedLog = eventLog |> Seq.rev |> Seq.toList + let expected = [ Started, key; Started, key; Finished, key ] + + Assert.Equal<_ list>(expected, orderedLog) + } + +[] +let ``Job is restarted if first requestor cancels but keeps running if second requestor cancels`` () = + task { + let jobStarted = new ManualResetEvent(false) + + let jobCanComplete = new ManualResetEvent(false) + + let computation key = node { + jobStarted.Set() |> ignore + waitFor jobCanComplete + return key * 2 + } + + let eventLog = ConcurrentStack() + let memoize = AsyncMemoize() + memoize.OnEvent(fun (e, (_label, k, _version)) -> eventLog.Push (e, k)) + + use cts1 = new CancellationTokenSource() + use cts2 = new CancellationTokenSource() + use cts3 = new CancellationTokenSource() + + let key = 1 + + let _task1 = NodeCode.StartAsTask_ForTesting( memoize.Get'(key, computation key), ct = cts1.Token) + + jobStarted.WaitOne() |> ignore + jobStarted.Reset() |> ignore + + let _task2 = NodeCode.StartAsTask_ForTesting( memoize.Get'(key, computation key), ct = cts2.Token) + let _task3 = NodeCode.StartAsTask_ForTesting( memoize.Get'(key, computation key), ct = cts3.Token) + + cts1.Cancel() + + jobStarted.WaitOne() |> ignore + + cts2.Cancel() + + jobCanComplete.Set() |> ignore + + let! result = _task3 + Assert.Equal(2, result) + + let orderedLog = eventLog |> Seq.rev |> Seq.toList + let expected = [ Started, key; Started, key; Finished, key ] + + Assert.Equal<_ list>(expected, orderedLog) + } + + +type ExpectedException() = + inherit Exception() + +[] +let ``Stress test`` () = + + let seed = System.Random().Next() + + let rng = System.Random seed + let threads = 30 + let iterations = 30 + let maxDuration = 100 + let minTimeout = 0 + let maxTimeout = 500 + let exceptionProbability = 0.01 + let gcProbability = 0.1 + let stepMs = 10 + let keyCount = rng.Next(5, 200) + let keys = [| 1 .. keyCount |] + + let testTimeoutMs = threads * iterations * maxDuration + + let intenseComputation durationMs result = + async { + if rng.NextDouble() < exceptionProbability then + raise (ExpectedException()) + let s = Stopwatch.StartNew() + let mutable number = 0 + while (int s.ElapsedMilliseconds) < durationMs do + number <- number + 1 % 12345 + return [result] + } |> NodeCode.AwaitAsync + + let rec sleepyComputation durationMs result = + node { + if rng.NextDouble() < (exceptionProbability / (float durationMs / float stepMs)) then + raise (ExpectedException()) + if durationMs > 0 then + do! Async.Sleep (min stepMs durationMs) |> NodeCode.AwaitAsync + return! sleepyComputation (durationMs - stepMs) result + else + return [result] + } + + let rec mixedComputation durationMs result = + node { + if durationMs > 0 then + if rng.NextDouble() < 0.5 then + let! _ = intenseComputation (min stepMs durationMs) () + () + else + let! _ = sleepyComputation (min stepMs durationMs) () + () + return! mixedComputation (durationMs - stepMs) result + else + return [result] + } + + let computations = [| + intenseComputation + sleepyComputation + mixedComputation + |] + + let cache = AsyncMemoize(keepStrongly=5, keepWeakly=10) + + let mutable started = 0 + let mutable canceled = 0 + let mutable timeout = 0 + let mutable failed = 0 + let mutable completed = 0 + + let test = + seq { + for _ in 1..threads do + let rec loop iteration = + task { + if gcProbability > rng.NextDouble() then + GC.Collect(2, GCCollectionMode.Forced, false) + + let computation = computations[rng.Next computations.Length] + let durationMs = rng.Next maxDuration + let timeoutMs = rng.Next(minTimeout, maxTimeout) + let key = keys[rng.Next keys.Length] + let result = key * 2 + let job = cache.Get'(key, computation durationMs result) + let cts = new CancellationTokenSource() + let runningJob = NodeCode.StartAsTask_ForTesting(job, ct = cts.Token) + cts.CancelAfter timeoutMs + Interlocked.Increment &started |> ignore + try + let! actual = runningJob + Assert.Equal(result, actual.Head) + Interlocked.Increment &completed |> ignore + with + | :? TaskCanceledException as _e -> + Interlocked.Increment &canceled |> ignore + | :? OperationCanceledException as _e -> + Interlocked.Increment &canceled |> ignore + | :? TimeoutException -> Interlocked.Increment &timeout |> ignore + | :? ExpectedException -> Interlocked.Increment &failed |> ignore + | :? AggregateException as ex when + ex.Flatten().InnerExceptions |> Seq.exists (fun e -> e :? ExpectedException) -> + Interlocked.Increment &failed |> ignore + | e -> + failwith $"Seed {seed} failed on iteration {iteration}: %A{e}" + if iteration < iterations then + return! loop (iteration + 1) + return () + } + loop 1 + } + |> Task.WhenAll + + if not (test.Wait testTimeoutMs) then failwith "Test timed out - most likely deadlocked" + + Assert.Equal (threads * iterations, started) + // Assert.Equal((0,0,0,0,0),(started, completed, canceled, failed, timeout)) + Assert.Equal (started, completed + canceled + failed + timeout) + + Assert.True ((float completed) > ((float started) * 0.1), "Less than 10 % completed jobs") + + +[] +[] +[] +let ``Cancel running jobs with the same key`` cancelDuplicate expectFinished = + task { + let cache = AsyncMemoize(cancelDuplicateRunningJobs=cancelDuplicate) + + let mutable started = 0 + let mutable finished = 0 + + let job1started = new ManualResetEvent(false) + let job1finished = new ManualResetEvent(false) + + let jobCanContinue = new ManualResetEvent(false) + + let job2started = new ManualResetEvent(false) + let job2finished = new ManualResetEvent(false) + + let work onStart onFinish = node { + Interlocked.Increment &started |> ignore + onStart() |> ignore + waitFor jobCanContinue + do! spinFor (TimeSpan.FromMilliseconds 100) + Interlocked.Increment &finished |> ignore + onFinish() |> ignore + } + + let key1 = + { new ICacheKey<_, _> with + member _.GetKey() = 1 + member _.GetVersion() = 1 + member _.GetLabel() = "key1" } + + cache.Get(key1, work job1started.Set job1finished.Set) |> Async.AwaitNodeCode |> Async.Start + + waitFor job1started + + let key2 = + { new ICacheKey<_, _> with + member _.GetKey() = key1.GetKey() + member _.GetVersion() = key1.GetVersion() + 1 + member _.GetLabel() = "key2" } + + cache.Get(key2, work job2started.Set job2finished.Set ) |> Async.AwaitNodeCode |> Async.Start + + waitFor job2started + + jobCanContinue.Set() |> ignore + + waitFor job2finished + + if not cancelDuplicate then + waitFor job1finished + + Assert.Equal((2, expectFinished), (started, finished)) + } + + +type DummyException(msg) = + inherit Exception(msg) + +[] +let ``Preserve thread static diagnostics`` () = + + let seed = System.Random().Next() + + let rng = System.Random seed + + let job1Cache = AsyncMemoize() + let job2Cache = AsyncMemoize() + + let job1 (input: string) = node { + let! _ = Async.Sleep (rng.Next(1, 30)) |> NodeCode.AwaitAsync + let ex = DummyException("job1 error") + DiagnosticsThreadStatics.DiagnosticsLogger.ErrorR(ex) + return Ok input + } + + let job2 (input: int) = node { + + DiagnosticsThreadStatics.DiagnosticsLogger.Warning(DummyException("job2 error 1")) + + let! _ = Async.Sleep (rng.Next(1, 30)) |> NodeCode.AwaitAsync + + let key = { new ICacheKey<_, _> with + member _.GetKey() = "job1" + member _.GetVersion() = input + member _.GetLabel() = "job1" } + + let! result = job1Cache.Get(key, job1 "${input}" ) + + DiagnosticsThreadStatics.DiagnosticsLogger.Warning(DummyException("job2 error 2")) + + return input, result + + } + + let tasks = seq { + for i in 1 .. 100 do + + task { + let diagnosticsLogger = + CompilationDiagnosticLogger($"Testing task {i}", FSharpDiagnosticOptions.Default) + + use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Optimize) + + DiagnosticsThreadStatics.DiagnosticsLogger.Warning(DummyException("task error")) + + + let key = { new ICacheKey<_, _> with + member _.GetKey() = "job2" + member _.GetVersion() = rng.Next(1, 10) + member _.GetLabel() = "job2" } + + let! result = job2Cache.Get(key, job2 (i % 10)) |> Async.AwaitNodeCode + + let diagnostics = diagnosticsLogger.GetDiagnostics() + + //Assert.Equal(3, diagnostics.Length) + + return result, diagnostics + } + } + + let results = (Task.WhenAll tasks).Result + + let _diagnosticCounts = results |> Seq.map snd |> Seq.map Array.length |> Seq.groupBy id |> Seq.map (fun (k, v) -> k, v |> Seq.length) |> Seq.sortBy fst |> Seq.toList + + //Assert.Equal<(int * int) list>([4, 100], diagnosticCounts) + + let diagnosticMessages = results |> Seq.map snd |> Seq.map (Array.map (fun (d, _) -> d.Exception.Message) >> Array.toList) |> Set + + Assert.Equal>(Set [["task error"; "job2 error 1"; "job1 error"; "job2 error 2"; ]], diagnosticMessages) + + +[] +let ``Preserve thread static diagnostics already completed job`` () = + + let cache = AsyncMemoize() + + let key = { new ICacheKey<_, _> with + member _.GetKey() = "job1" + member _.GetVersion() = 1 + member _.GetLabel() = "job1" } + + let job (input: string) = node { + let ex = DummyException($"job {input} error") + DiagnosticsThreadStatics.DiagnosticsLogger.ErrorR(ex) + return Ok input + } + + async { + + let diagnosticsLogger = CompilationDiagnosticLogger($"Testing", FSharpDiagnosticOptions.Default) + + use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Optimize) + + let! _ = cache.Get(key, job "1" ) |> Async.AwaitNodeCode + let! _ = cache.Get(key, job "2" ) |> Async.AwaitNodeCode + + let diagnosticMessages = diagnosticsLogger.GetDiagnostics() |> Array.map (fun (d, _) -> d.Exception.Message) |> Array.toList + + Assert.Equal>(["job 1 error"; "job 1 error"], diagnosticMessages) + + } + |> Async.StartAsTask + + +[] +let ``We get diagnostics from the job that failed`` () = + + let cache = AsyncMemoize() + + let key = { new ICacheKey<_, _> with + member _.GetKey() = "job1" + member _.GetVersion() = 1 + member _.GetLabel() = "job1" } + + let job (input: int) = node { + let ex = DummyException($"job {input} error") + do! Async.Sleep 100 |> NodeCode.AwaitAsync + DiagnosticsThreadStatics.DiagnosticsLogger.Error(ex) + return 5 + } + + let result = + [1; 2] + |> Seq.map (fun i -> + async { + let diagnosticsLogger = CompilationDiagnosticLogger($"Testing", FSharpDiagnosticOptions.Default) + + use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Optimize) + try + let! _ = cache.Get(key, job i ) |> Async.AwaitNodeCode + () + with _ -> + () + let diagnosticMessages = diagnosticsLogger.GetDiagnostics() |> Array.map (fun (d, _) -> d.Exception.Message) |> Array.toList + + return diagnosticMessages + }) + |> Async.Parallel + |> Async.StartAsTask + |> (fun t -> t.Result) + |> Array.toList + + Assert.True( + result = [["job 1 error"]; ["job 1 error"]] || + result = [["job 2 error"]; ["job 2 error"]] ) diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/LruCache.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/LruCache.fs new file mode 100644 index 00000000000..a477f7e6f7c --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/LruCache.fs @@ -0,0 +1,197 @@ +module CompilerService.LruCache +open Internal.Utilities.Collections + +open Xunit +open System + +[] +let ``Adding an item to the cache should make it retrievable``() = + let cache = new LruCache(keepStrongly = 2) + cache.Set(1, "one") + let result = cache.TryGet(1) + Assert.Equal("one", result.Value) + +[] +let ``Adding an item to the cache should evict the least recently used item if the cache is full``() = + let cache = new LruCache(keepStrongly = 2, keepWeakly = 0) + cache.Set(1, "one") + cache.Set(2, "two") + cache.Set(3, "three") + let result = cache.TryGet(1) + Assert.Null(result) + +[] +let ``Adding an item to the cache should not evict a required item``() = + let cache = new LruCache(keepStrongly = 2, requiredToKeep = (fun v -> v = "one")) + cache.Set(1, "one") + cache.Set(2, "two") + cache.Set(3, "three") + let result = cache.TryGet(1) + Assert.Equal("one", result.Value) + +[] +let ``Adding an item to the cache should not evict a strongly kept item``() = + let cache = new LruCache(keepStrongly = 2, keepWeakly = 0) + cache.Set(1, "one") + cache.Set(2, "two") + cache.Set(1, "one") + cache.Set(3, "three") + let result = cache.TryGet(1) + Assert.Equal("one", result.Value) + +[] +let ``Adding an item to the cache should not evict a strongly kept item, even if it is the least recently used``() = + let cache = new LruCache(keepStrongly = 2, keepWeakly = 0, requiredToKeep = (fun v -> v = "one")) + cache.Set(1, "one") + cache.Set(2, "two") + cache.Set(3, "three") + let result = cache.TryGet(1) + Assert.Equal("one", result.Value) + +[] +let ``Adding an item to the cache should not evict a weakly kept item if its reference is still valid``() = + let cache = new LruCache(keepStrongly = 2, keepWeakly = 1) + let value = "one" + cache.Set(1, value) + cache.Set(2, "two") + GC.Collect(2, GCCollectionMode.Forced, true) + let result = cache.TryGet(1) + Assert.Equal(value, result.Value) + + +// Doing this directly in the test prevents GC for some reason +let private addObjToCache (cache: LruCache<_, int,_>) key = + let o = obj () + cache.Set(key, o) + +[] +let ``Adding an item to the cache should evict a weakly kept item if its reference is no longer valid``() = + let cache = new LruCache<_, int, _>(keepStrongly = 2, keepWeakly = 1) + addObjToCache cache 1 + addObjToCache cache 2 + addObjToCache cache 3 + GC.Collect(2, GCCollectionMode.Forced, true) + + let result = cache.TryGet(1) + Assert.True(result.IsNone) + + +[] +let ``When a new version is added other versions get weakened`` () = + let eventLog = ResizeArray() + + let cache = new LruCache<_, int, _>(keepStrongly = 2, keepWeakly = 2, event = (fun e v -> eventLog.Add(e, v))) + + cache.Set(1, 1, "one1") + cache.Set(1, 2, "one2") + cache.Set(1, 3, "one3") + cache.Set(1, 4, "one4") + + let expected = [ + CacheEvent.Weakened, ("[no label]", 1, 1) + CacheEvent.Weakened, ("[no label]", 1, 2) + CacheEvent.Weakened, ("[no label]", 1, 3) + CacheEvent.Evicted, ("[no label]", 1, 1) + ] + + Assert.Equal>(expected, eventLog |> Seq.toList) + +[] +let ``When a new version is added other versions don't get weakened when they're required to keep`` () = + let eventLog = ResizeArray() + + let cache = new LruCache<_, int, _>(keepStrongly = 2, keepWeakly = 2, requiredToKeep = ((=) "one1"), event = (fun e v -> eventLog.Add(e, v))) + + cache.Set(1, 1, "one1") + cache.Set(1, 2, "one2") + cache.Set(1, 3, "one3") + cache.Set(1, 4, "one4") + + let expected = [ + CacheEvent.Weakened, ("[no label]", 1, 2) + CacheEvent.Weakened, ("[no label]", 1, 3) + ] + + Assert.Equal>(expected, eventLog |> Seq.toList) + +[] +let ``Looking up a weakened item will strengthen it`` () = + let eventLog = ResizeArray() + + let cache = new LruCache<_, int, _>(keepStrongly = 2, keepWeakly = 2, event = (fun e v -> eventLog.Add(e, v))) + + cache.Set(1, 1, "one1") + cache.Set(1, 2, "one2") + cache.Set(1, 3, "one3") + cache.Set(1, 4, "one4") + + let result = cache.TryGet(1, 2) + Assert.Equal("one2", result.Value) + + let expected = [ + CacheEvent.Weakened, ("[no label]", 1, 1) + CacheEvent.Weakened, ("[no label]", 1, 2) + CacheEvent.Weakened, ("[no label]", 1, 3) + CacheEvent.Evicted, ("[no label]", 1, 1) + CacheEvent.Strengthened, ("[no label]", 1, 2) + ] + + Assert.Equal>(expected, eventLog |> Seq.toList) + + +[] +let ``New version doesn't push other keys out of strong list``() = + + let eventLog = ResizeArray() + + let cache = new LruCache<_, int, _>(keepStrongly = 2, keepWeakly = 2, event = (fun e v -> eventLog.Add(e, v))) + + cache.Set(1, 1, "one1") + cache.Set(1, 2, "one2") + cache.Set(1, 3, "one3") + cache.Set(1, 4, "one4") + cache.Set(2, 1, "two1") + cache.Set(2, 2, "two2") + + let expected = [ + CacheEvent.Weakened, ("[no label]", 1, 1) + CacheEvent.Weakened, ("[no label]", 1, 2) + CacheEvent.Weakened, ("[no label]", 1, 3) + CacheEvent.Evicted, ("[no label]", 1, 1) + CacheEvent.Weakened, ("[no label]", 2, 1) + CacheEvent.Evicted, ("[no label]", 1, 2) + ] + + Assert.Equal>(expected, eventLog |> Seq.toList) + +[] +let ``We can clear specific keys based on a predicate``() = + + let eventLog = ResizeArray() + + let cache = new LruCache<_, int, _>(keepStrongly = 2, keepWeakly = 2, event = (fun e v -> eventLog.Add(e, v))) + + cache.Set(1, 1, "one1") + cache.Set(1, 2, "one2") + cache.Set(1, 3, "one3") + cache.Set(1, 4, "one4") + cache.Set(2, 1, "two1") + cache.Set(2, 2, "two2") + + cache.Clear((=) 1) + + let result = cache.TryGet(1, 2) + Assert.True(result.IsNone) + + let expected = [ + CacheEvent.Weakened, ("[no label]", 1, 1) + CacheEvent.Weakened, ("[no label]", 1, 2) + CacheEvent.Weakened, ("[no label]", 1, 3) + CacheEvent.Evicted, ("[no label]", 1, 1) + CacheEvent.Weakened, ("[no label]", 2, 1) + CacheEvent.Evicted, ("[no label]", 1, 2) + CacheEvent.Cleared, ("[no label]", 1, 3) + CacheEvent.Cleared, ("[no label]", 1, 4) + ] + + Assert.Equal>(expected, eventLog |> Seq.toList) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/ValueRestriction/E_NotMemberOrFunction01.fsx b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/ValueRestriction/E_NotMemberOrFunction01.fsx index 182fb04be48..5cb7755a083 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/ValueRestriction/E_NotMemberOrFunction01.fsx +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/ValueRestriction/E_NotMemberOrFunction01.fsx @@ -1,6 +1,6 @@ // #Conformance #ObjectOrientedTypes #Classes #TypeInference #ValueRestriction -//Value restriction\. The value 'x1' has been inferred to have generic type. val x1: \('_a -> unit\) .Either make the arguments to 'x1' explicit or, if you do not intend for it to be generic, add a type annotation\.$ +//Value restriction: The value 'x1' has an inferred generic function type val x1: \('_a -> unit\)However, values cannot have generic type variables like '_a in "let f: '_a". You should define 'x1' as a function instead by doing one of the following:- Add an explicit parameter that is applied instead of using a partial application "let f param"- Add a unit parameter like "let f\(\)"- Write explicit type parameters like "let f<'a>"or if you do not intend for it to be generic, either:- Add an explicit type annotation like "let f : obj -> obj"- Apply arguments of non-generic types to the function value in later code for type inference like "do f\(\)"\.This error is because a let binding without parameters defines a value, not a function\. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results\.$ // We expect a value restriction here. The inferred signature is: // val x1: (?1 -> unit) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ComputationExpressions/CustomOperations.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ComputationExpressions/CustomOperations.fs new file mode 100644 index 00000000000..28e9ff22c7a --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ComputationExpressions/CustomOperations.fs @@ -0,0 +1,43 @@ +namespace Conformance.Expressions.ComputationExpressions + +open Xunit +open FSharp.Test.Compiler + +module CustomOperations = + + [] + let ``[] without explicit name is allowed, uses method name as operation name`` () = + FSharp """ + module CustomOperationTest + type CBuilder() = + [] + member this.Foo _ = "Foo" + [] + member this.foo _ = "foo" + [] + member this.bar _ = "bar" + member this.Yield _ = () + member this.Zero _ = () + + + [] + let main _ = + let cb = CBuilder() + + let x = cb { Foo } + let y = cb { foo } + let z = cb { bar } + printfn $"{x}" + printfn $"{y}" + + if x <> "Foo" then + failwith "not Foo" + if y <> "foo" then + failwith "not foo" + if z <> "bar" then + failwith "not bar" + 0 + """ + |> asExe + |> compileAndRun + |> shouldSucceed \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs index 6ef849136ae..03e543491ac 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs @@ -72,6 +72,7 @@ let foo = { new Foo() with member __.ToString() = base.ToString() } |> typecheck |> shouldFail |> withDiagnostics [ + (Error 759, Line 5, Col 13, Line 5, Col 22, "Instances of this type cannot be created since it has been marked abstract or not all methods have been given implementations. Consider using an object expression '{ new ... with ... }' instead."); (Error 738, Line 5, Col 11, Line 5, Col 24, "Invalid object expression. Objects without overrides or interfaces should use the expression form 'new Type(args)' without braces.") (Error 740, Line 5, Col 11, Line 5, Col 24, "Invalid record, sequence or computation expression. Sequence expressions should be of the form 'seq { ... }'") ] diff --git a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs index 3bb1770b411..b3c33031acb 100644 --- a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs +++ b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs @@ -74,3 +74,43 @@ type DataItem< ^input> with """ |> compile |> shouldSucceed + + [] + let ``Indirect constraint by operator`` () = + FSharp """ +List.average [42] |> ignore +""" + |> typecheck + |> shouldFail + |> withSingleDiagnostic + (Error 1, Line 2, Col 15, Line 2, Col 17, "'List.average' does not support the type 'int', because the latter lacks the required (real or built-in) member 'DivideByInt'") + + [] + let ``Direct constraint by named (pseudo) operator`` () = + FSharp """ +abs -1u |> ignore +""" + |> typecheck + |> shouldFail + |> withSingleDiagnostic + (Error 1, Line 2, Col 6, Line 2, Col 8, "The type 'uint32' does not support the operator 'abs'") + + [] + let ``Direct constraint by simple operator`` () = + FSharp """ +"" >>> 1 |> ignore +""" + |> typecheck + |> shouldFail + |> withSingleDiagnostic + (Error 1, Line 2, Col 1, Line 2, Col 3, "The type 'string' does not support the operator '>>>'") + + [] + let ``Direct constraint by pseudo operator`` () = + FSharp """ +ignore ["1" .. "42"] +""" + |> typecheck + |> shouldFail + |> withSingleDiagnostic + (Error 1, Line 2, Col 9, Line 2, Col 12, "The type 'string' does not support the operator 'op_Range'") diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl index 66fa1c78b4d..e092d8fd8ea 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.net472.bsl @@ -432,14 +432,14 @@ } .method public static class TestModule/MyNullableOption`1 - mapPossiblyNullable(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f, - class TestModule/MyNullableOption`1 myOpt) cil managed + mapPossiblyNullable(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f, + class TestModule/MyNullableOption`1 myOpt) cil managed { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) .param type a .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) .param type b - .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) + .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) .maxstack 4 .locals init (class TestModule/MyNullableOption`1 V_0, diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl index 31eb914a6f2..d48f01435d7 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullAsTrueValue.fs.il.netcore.bsl @@ -432,14 +432,14 @@ } .method public static class TestModule/MyNullableOption`1 - mapPossiblyNullable(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f, - class TestModule/MyNullableOption`1 myOpt) cil managed + mapPossiblyNullable(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f, + class TestModule/MyNullableOption`1 myOpt) cil managed { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) .param type a .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) .param type b - .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) .maxstack 4 .locals init (class TestModule/MyNullableOption`1 V_0, diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/VeryLargeClasses.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/VeryLargeClasses.fs new file mode 100644 index 00000000000..8819cf27cdc --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/VeryLargeClasses.fs @@ -0,0 +1,50 @@ +namespace EmittedIL + +open Microsoft.FSharp.Core +open Xunit +open FSharp.Test.Compiler + +module VeryLargeClasses = + + let classWithManyMethods n = + let methods = + let mutable source = "" + for i = 0 to n - 1 do + source <- source + $""" + static member Method%05x{i}() = () """ + source + + FSharp + $""" + namespace VeryLargeClassesTestcases + + type Type1 ={methods} + """ + + [] + let ``More than 64K Methods -- should fail`` () = + classWithManyMethods (1024 * 64 + 1) + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 3864, Line 1, Col 1, Line 1, Col 1, "The type 'VeryLargeClassesTestcases.Type1' has too many methods. Found: '65537', maximum: '65520'") + ] + + [] + let ``Exactly (0xfff0) Methods -- should succeed`` () = + FSharp + """ +module MyMain +open System +open System.Reflection +do printfn $"location: {typeof.Assembly.Location}" +let asm = Assembly.LoadFrom(typeof.Assembly.Location) +printfn $"asm: {asm}" +let types = asm.GetTypes() +printfn "length: {types.Length}" +""" + |> withReferences [ classWithManyMethods 0xfff0 |> asLibrary ] + |> asExe + |> compileAndRun + |> shouldSucceed + diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ExtendedDiagnosticDataTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ExtendedDiagnosticDataTests.fs index fea4dfddbb7..eec3ce03dcd 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ExtendedDiagnosticDataTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ExtendedDiagnosticDataTests.fs @@ -143,8 +143,10 @@ if true then 1 else "a" Assert.Equal("int", typeMismatch.ExpectedType.Format(displayContext)) Assert.Equal("string", typeMismatch.ActualType.Format(displayContext))) -[] -let ``ArgumentsInSigAndImplMismatchExtendedData 01`` () = +[] +[] +[] +let ``ArgumentsInSigAndImplMismatchExtendedData 01`` useTransparentCompiler = let encodeFsi = Fsi """ module Test @@ -157,7 +159,7 @@ let f (y: int) = () """ encodeFsi |> withAdditionalSourceFile encodeFs - |> typecheckProject true + |> typecheckProject true useTransparentCompiler |> checkDiagnostic (3218, "The argument names in the signature 'x' and implementation 'y' do not match. The argument name from the signature file will be used. This may cause problems when debugging or profiling.") (fun (argsMismatch: ArgumentsInSigAndImplMismatchExtendedData) -> @@ -166,8 +168,10 @@ let f (y: int) = () Assert.True(argsMismatch.SignatureRange.FileName.EndsWith("fsi")) Assert.True(argsMismatch.ImplementationRange.FileName.EndsWith("fs"))) -[] -let ``FieldNotContainedDiagnosticExtendedData 01`` () = +[] +[] +[] +let ``FieldNotContainedDiagnosticExtendedData 01`` useTransparentCompiler = let encodeFsi = Fsi """ namespace rec Foo @@ -182,7 +186,7 @@ type A = """ encodeFsi |> withAdditionalSourceFile encodeFs - |> typecheckProject true + |> typecheckProject true useTransparentCompiler |> checkDiagnostic (193, "The module contains the field\n myStatic: int \nbut its signature specifies\n myStatic: int \nthe accessibility specified in the signature is more than that specified in the implementation") (fun (fieldsData: FieldNotContainedDiagnosticExtendedData) -> diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs index 3366ed91c3f..9bad5b4d0af 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs @@ -1486,3 +1486,29 @@ namespace N Message = "The TailCall attribute should only be applied to recursive functions." } ] + + [] + let ``Warn about self-defined attribute`` () = // is the analysis available for users of older FSharp.Core versions + """ +module Microsoft.FSharp.Core + + open System + + [] + type TailCallAttribute() = inherit Attribute() + + [] + let rec f x = 1 + f x + """ + |> FSharp + |> compile + |> shouldFail + |> withResults [ + { Error = Warning 3569 + Range = { StartLine = 10 + StartColumn = 23 + EndLine = 10 + EndColumn = 26 } + Message = + "The member or function 'f' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way." } + ] diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 56e23439441..857cbdb7d2c 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -19,6 +19,7 @@ $(DefineConstants);DEBUG true + true @@ -71,13 +72,14 @@ - + + @@ -124,6 +126,7 @@ + @@ -268,6 +271,9 @@ + + + @@ -296,16 +302,17 @@ + + - - - - %(RelativeDir)TestSource\%(Filename)%(Extension) + %(RelativeDir)TestSource\%(Filename)%(Extension) + + %(RelativeDir)\BaseLine\%(Filename)%(Extension) diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/CommonWorkflows.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/CommonWorkflows.fs index ce9846a0ee5..f4c5c41770d 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/CommonWorkflows.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/CommonWorkflows.fs @@ -100,13 +100,14 @@ let ``Changes in a referenced project`` () = checkFile "Last" expectSignatureChanged } -[] -let ``Language service works if the same file is listed twice`` () = +[] +// TODO: This will probably require some special care in TransparentCompiler... +let ``Language service works if the same file is listed twice`` () = let file = sourceFile "First" [] - let project = SyntheticProject.Create(file) + let project = SyntheticProject.Create(file, file) project.Workflow { - checkFile "First" expectOk - addFileAbove "First" file + // checkFile "First" expectOk + // addFileAbove "First" file checkFile "First" (expectSingleWarningAndNoErrors "Please verify that it is included only once in the project file.") } diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/FindReferences.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/FindReferences.fs index c8cff9112c2..b12edf8cb6d 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/FindReferences.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/FindReferences.fs @@ -5,6 +5,8 @@ open FSharp.Compiler.CodeAnalysis open FSharp.Test.ProjectGeneration open FSharp.Test.ProjectGeneration.Helpers +#nowarn "57" + type Occurence = Definition | InType | Use let deriveOccurence (su:FSharpSymbolUse) = @@ -344,7 +346,7 @@ and mytype = MyType let symbolUse = getSymbolUse fileName source "MyType" options checker |> Async.RunSynchronously - checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol, fastCheck = true) + checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol) |> Async.RunSynchronously |> expectToFind [ fileName, 2, 5, 11 @@ -430,7 +432,7 @@ match 2 with let symbolUse = getSymbolUse fileName source "Even" options checker |> Async.RunSynchronously - checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol, fastCheck = true) + checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol) |> Async.RunSynchronously |> expectToFind [ fileName, 2, 6, 10 @@ -463,7 +465,7 @@ module Two = let symbolUse = getSymbolUse fileName source "Even" options checker |> Async.RunSynchronously - checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol, fastCheck = true) + checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol) |> Async.RunSynchronously |> expectToFind [ fileName, 4, 10, 14 @@ -619,7 +621,7 @@ let y = MyType.Two let symbolUse = getSymbolUse fileName source "MyType" options checker |> Async.RunSynchronously - checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol, fastCheck = true) + checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol) |> Async.RunSynchronously |> expectToFind [ fileName, 4, 5, 11 @@ -648,7 +650,7 @@ let y = MyType.Three let symbolUse = getSymbolUse fileName source "MyType" options checker |> Async.RunSynchronously - checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol, fastCheck = true) + checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol) |> Async.RunSynchronously |> expectToFind [ fileName, 4, 7, 13 diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/ProjectSnapshot.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/ProjectSnapshot.fs new file mode 100644 index 00000000000..90e28cc63ac --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/ProjectSnapshot.fs @@ -0,0 +1,104 @@ +module FSharpChecker.ProjectSnapshot + +open Xunit +open System +open FSharp.Compiler.CodeAnalysis.ProjectSnapshot + + +// TODO: restore tests + +//[] +//let WithoutImplFilesThatHaveSignatures () = + +// let snapshot = FSharpProjectSnapshot.Create( +// projectFileName = "Dummy.fsproj", +// projectId = None, +// sourceFiles = [ +// { FileName = "A.fsi"; Version = "1"; GetSource = Unchecked.defaultof<_> } +// { FileName = "A.fs"; Version = "1"; GetSource = Unchecked.defaultof<_> } +// { FileName = "B.fs"; Version = "1"; GetSource = Unchecked.defaultof<_> } +// { FileName = "C.fsi"; Version = "1"; GetSource = Unchecked.defaultof<_> } +// { FileName = "C.fs"; Version = "1"; GetSource = Unchecked.defaultof<_> } +// ], +// referencesOnDisk = [], +// otherOptions = [], +// referencedProjects = [], +// isIncompleteTypeCheckEnvironment = true, +// useScriptResolutionRules = false, +// loadTime = DateTime(1234, 5, 6), +// unresolvedReferences = None, +// originalLoadReferences = [], +// stamp = None +// ) + +// let result = snapshot.WithoutImplFilesThatHaveSignatures + +// let expected = [| "A.fsi"; "B.fs"; "C.fsi" |] + +// Assert.Equal(expected, result.SourceFileNames |> List.toArray) + +// Assert.Equal(result.FullVersion, snapshot.SignatureVersion) + +//[] +//let WithoutImplFilesThatHaveSignaturesExceptLastOne () = + +// let snapshot = FSharpProjectSnapshot.Create( +// projectFileName = "Dummy.fsproj", +// projectId = None, +// sourceFiles = [ +// { FileName = "A.fsi"; Version = "1"; GetSource = Unchecked.defaultof<_> } +// { FileName = "A.fs"; Version = "1"; GetSource = Unchecked.defaultof<_> } +// { FileName = "B.fs"; Version = "1"; GetSource = Unchecked.defaultof<_> } +// { FileName = "C.fsi"; Version = "1"; GetSource = Unchecked.defaultof<_> } +// { FileName = "C.fs"; Version = "1"; GetSource = Unchecked.defaultof<_> } +// ], +// referencesOnDisk = [], +// otherOptions = [], +// referencedProjects = [], +// isIncompleteTypeCheckEnvironment = true, +// useScriptResolutionRules = false, +// loadTime = DateTime(1234, 5, 6), +// unresolvedReferences = None, +// originalLoadReferences = [], +// stamp = None +// ) + +// let result = snapshot.WithoutImplFilesThatHaveSignaturesExceptLastOne + +// let expected = [| "A.fsi"; "B.fs"; "C.fsi"; "C.fs" |] + +// Assert.Equal(expected, result.SourceFileNames |> List.toArray) + +// Assert.Equal(result.FullVersion, snapshot.LastFileVersion) + + +//[] +//let WithoutImplFilesThatHaveSignaturesExceptLastOne_2 () = + +// let snapshot = FSharpProjectSnapshot.Create( +// projectFileName = "Dummy.fsproj", +// projectId = None, +// sourceFiles = [ +// { FileName = "A.fs"; Version = "1"; GetSource = Unchecked.defaultof<_> } +// { FileName = "B.fs"; Version = "1"; GetSource = Unchecked.defaultof<_> } +// { FileName = "C.fs"; Version = "1"; GetSource = Unchecked.defaultof<_> } +// ], +// referencesOnDisk = [], +// otherOptions = [], +// referencedProjects = [], +// isIncompleteTypeCheckEnvironment = true, +// useScriptResolutionRules = false, +// loadTime = DateTime(1234, 5, 6), +// unresolvedReferences = None, +// originalLoadReferences = [], +// stamp = None +// ) + +// let result = snapshot.WithoutImplFilesThatHaveSignaturesExceptLastOne + +// let expected = [| "A.fs"; "B.fs"; "C.fs" |] + +// Assert.Equal(expected, result.SourceFileNames |> List.toArray) + +// Assert.Equal(result.FullVersion, snapshot.LastFileVersion) + diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs new file mode 100644 index 00000000000..57a9e266fe8 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs @@ -0,0 +1,803 @@ +module FSharpChecker.TransparentCompiler + +open System.Collections.Concurrent +open System.Diagnostics +open FSharp.Compiler.CodeAnalysis +open Internal.Utilities.Collections +open FSharp.Compiler.CodeAnalysis.TransparentCompiler +open Internal.Utilities.Library.Extras +open FSharp.Compiler.GraphChecking.GraphProcessing +open FSharp.Compiler.Diagnostics + +open Xunit + +open FSharp.Test.ProjectGeneration +open FSharp.Test.ProjectGeneration.Helpers +open System.IO +open Microsoft.CodeAnalysis +open System +open System.Threading.Tasks +open System.Threading +open TypeChecks + +open OpenTelemetry +open OpenTelemetry.Resources +open OpenTelemetry.Trace + + +#nowarn "57" + +[] +let ``Use Transparent Compiler`` () = + + let size = 20 + + let project = + { SyntheticProject.Create() with + SourceFiles = [ + sourceFile $"File%03d{0}" [] + for i in 1..size do + sourceFile $"File%03d{i}" [$"File%03d{i-1}"] + ] + } + + let first = "File001" + let middle = $"File%03d{size / 2}" + let last = $"File%03d{size}" + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + updateFile first updatePublicSurface + checkFile first expectSignatureChanged + checkFile last expectSignatureChanged + updateFile middle updatePublicSurface + checkFile last expectSignatureChanged + addFileAbove middle (sourceFile "addedFile" [first]) + updateFile middle (addDependency "addedFile") + checkFile middle expectSignatureChanged + checkFile last expectSignatureChanged + } + +[] +let ``Parallel processing`` () = + + let project = SyntheticProject.Create( + sourceFile "A" [], + sourceFile "B" ["A"], + sourceFile "C" ["A"], + sourceFile "D" ["A"], + sourceFile "E" ["B"; "C"; "D"]) + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + checkFile "E" expectOk + updateFile "A" updatePublicSurface + saveFile "A" + + checkFile "E" expectSignatureChanged + } + +[] +let ``Parallel processing with signatures`` () = + + let project = SyntheticProject.Create( + sourceFile "A" [] |> addSignatureFile, + sourceFile "B" ["A"] |> addSignatureFile, + sourceFile "C" ["A"] |> addSignatureFile, + sourceFile "D" ["A"] |> addSignatureFile, + sourceFile "E" ["B"; "C"; "D"] |> addSignatureFile) + + //let cacheEvents = ConcurrentBag<_>() + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + //withChecker (fun checker -> checker.CacheEvent.Add cacheEvents.Add) + checkFile "E" expectOk + updateFile "A" updatePublicSurface + checkFile "E" expectNoChanges + regenerateSignature "A" + regenerateSignature "B" + regenerateSignature "C" + regenerateSignature "D" + regenerateSignature "E" + checkFile "E" expectSignatureChanged + } + +let makeTestProject () = + SyntheticProject.Create( + sourceFile "First" [], + sourceFile "Second" ["First"], + sourceFile "Third" ["First"], + { sourceFile "Last" ["Second"; "Third"] with EntryPoint = true }) + +let testWorkflow () = + ProjectWorkflowBuilder(makeTestProject(), useTransparentCompiler = true) + +[] +let ``Edit file, check it, then check dependent file`` () = + testWorkflow() { + updateFile "First" breakDependentFiles + checkFile "First" expectSignatureChanged + checkFile "Second" expectErrors + } + +[] +let ``Edit file, don't check it, check dependent file`` () = + testWorkflow() { + updateFile "First" breakDependentFiles + checkFile "Second" expectErrors + } + +[] +let ``Check transitive dependency`` () = + testWorkflow() { + updateFile "First" breakDependentFiles + checkFile "Last" expectSignatureChanged + } + +[] +let ``Change multiple files at once`` () = + testWorkflow() { + updateFile "First" (setPublicVersion 2) + updateFile "Second" (setPublicVersion 2) + updateFile "Third" (setPublicVersion 2) + checkFile "Last" (expectSignatureContains "val f: x: 'a -> (ModuleFirst.TFirstV_2<'a> * ModuleSecond.TSecondV_2<'a>) * (ModuleFirst.TFirstV_2<'a> * ModuleThird.TThirdV_2<'a>) * TLastV_1<'a>") + } + +[] +let ``Files depend on signature file if present`` () = + let project = makeTestProject() |> updateFile "First" addSignatureFile + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + updateFile "First" breakDependentFiles + saveFile "First" + checkFile "Second" expectNoChanges + } + +[] +let ``Project with signatures`` () = + + let project = SyntheticProject.Create( + { sourceFile "First" [] with + Source = "let f (x: int) = x" + SignatureFile = AutoGenerated }, + { sourceFile "Second" ["First"] with + Source = "let a x = ModuleFirst.f x" + SignatureFile = AutoGenerated }) + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + checkFile "Second" expectOk + } + +[] +let ``Signature update`` () = + + let project = SyntheticProject.Create( + { sourceFile "First" [] with + Source = "let f (x: int) = x" + SignatureFile = Custom "val f: x: int -> int" }, + { sourceFile "Second" ["First"] with + Source = "let a x = ModuleFirst.f x" }) + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + checkFile "Second" expectOk + updateFile "First" (fun f -> { f with SignatureFile = Custom "val f: x: string -> string" }) + checkFile "Second" expectSignatureChanged + } + +[] +let ``Adding a file`` () = + testWorkflow() { + addFileAbove "Second" (sourceFile "New" []) + updateFile "Second" (addDependency "New") + checkFile "Last" (expectSignatureContains "val f: x: 'a -> (ModuleFirst.TFirstV_1<'a> * ModuleNew.TNewV_1<'a> * ModuleSecond.TSecondV_1<'a>) * (ModuleFirst.TFirstV_1<'a> * ModuleThird.TThirdV_1<'a>) * TLastV_1<'a>") + } + +[] +let ``Removing a file`` () = + testWorkflow() { + removeFile "Second" + checkFile "Last" expectErrors + } + +[] +let ``Changes in a referenced project`` () = + let library = SyntheticProject.Create("library", sourceFile "Library" []) + + let project = + { makeTestProject() with DependsOn = [library] } + |> updateFile "First" (addDependency "Library") + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + + updateFile "First" updatePublicSurface + checkFile "Last" expectOk + + updateFile "Library" updatePublicSurface + saveFile "Library" + checkFile "Last" expectSignatureChanged + + } + +[] +let ``File is not checked twice`` () = + + let cacheEvents = ConcurrentQueue() + + testWorkflow() { + withChecker (fun checker -> + async { + do! Async.Sleep 50 // wait for events from initial project check + checker.Caches.TcIntermediate.OnEvent cacheEvents.Enqueue + }) + updateFile "First" updatePublicSurface + checkFile "Third" expectOk + } |> ignore + + let intermediateTypeChecks = + cacheEvents + |> Seq.groupBy (fun (_e, (_l, (f, _p), _)) -> f |> Path.GetFileName) + |> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList) + |> Map + + Assert.Equal([Weakened; Started; Finished], intermediateTypeChecks["FileFirst.fs"]) + Assert.Equal([Weakened; Started; Finished], intermediateTypeChecks["FileThird.fs"]) + +[] +let ``If a file is checked as a dependency it's not re-checked later`` () = + let cacheEvents = ConcurrentQueue() + + testWorkflow() { + withChecker (fun checker -> + async { + do! Async.Sleep 50 // wait for events from initial project check + checker.Caches.TcIntermediate.OnEvent cacheEvents.Enqueue + }) + updateFile "First" updatePublicSurface + checkFile "Last" expectOk + checkFile "Third" expectOk + } |> ignore + + let intermediateTypeChecks = + cacheEvents + |> Seq.groupBy (fun (_e, (_l, (f, _p), _)) -> f |> Path.GetFileName) + |> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList) + |> Map + + Assert.Equal([Weakened; Started; Finished], intermediateTypeChecks["FileThird.fs"]) + + +// [] TODO: differentiate complete and minimal checking requests +let ``We don't check files that are not depended on`` () = + let project = SyntheticProject.Create( + sourceFile "First" [], + sourceFile "Second" ["First"], + sourceFile "Third" ["First"], + sourceFile "Last" ["Third"]) + + let cacheEvents = ConcurrentQueue() + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + withChecker (fun checker -> + async { + do! Async.Sleep 50 // wait for events from initial project check + checker.Caches.TcIntermediate.OnEvent cacheEvents.Enqueue + }) + updateFile "First" updatePublicSurface + checkFile "Last" expectOk + } |> ignore + + let intermediateTypeChecks = + cacheEvents + |> Seq.groupBy (fun (_e, (_l, (f, _p), _)) -> Path.GetFileName f) + |> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList) + |> Map + + Assert.Equal([Started; Finished], intermediateTypeChecks["FileFirst.fs"]) + Assert.Equal([Started; Finished], intermediateTypeChecks["FileThird.fs"]) + Assert.False (intermediateTypeChecks.ContainsKey "FileSecond.fs") + +// [] TODO: differentiate complete and minimal checking requests +let ``Files that are not depended on don't invalidate cache`` () = + let project = SyntheticProject.Create( + sourceFile "First" [], + sourceFile "Second" ["First"], + sourceFile "Third" ["First"], + sourceFile "Last" ["Third"]) + + let cacheTcIntermediateEvents = ConcurrentQueue() + let cacheGraphConstructionEvents = ConcurrentQueue() + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + updateFile "First" updatePublicSurface + checkFile "Last" expectOk + withChecker (fun checker -> + async { + do! Async.Sleep 50 // wait for events from initial project check + checker.Caches.TcIntermediate.OnEvent cacheTcIntermediateEvents.Enqueue + checker.Caches.DependencyGraph.OnEvent cacheGraphConstructionEvents.Enqueue + + }) + updateFile "Second" updatePublicSurface + checkFile "Last" expectOk + } |> ignore + + let intermediateTypeChecks = + cacheTcIntermediateEvents + |> Seq.groupBy (fun (_e, (l, _k, _)) -> l) + |> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList) + |> Map + + let graphConstructions = + cacheGraphConstructionEvents + |> Seq.groupBy (fun (_e, (l, _k, _)) -> l) + |> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList) + |> Map + + Assert.Equal([Started; Finished], graphConstructions["FileLast.fs"]) + + Assert.Equal([], intermediateTypeChecks |> Map.toList) + +// [] TODO: differentiate complete and minimal checking requests +let ``Files that are not depended on don't invalidate cache part 2`` () = + let project = SyntheticProject.Create( + sourceFile "A" [], + sourceFile "B" ["A"], + sourceFile "C" ["A"], + sourceFile "D" ["B"; "C"], + sourceFile "E" ["C"]) + + let cacheTcIntermediateEvents = ConcurrentQueue() + let cacheGraphConstructionEvents = ConcurrentQueue() + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + updateFile "A" updatePublicSurface + checkFile "D" expectOk + withChecker (fun checker -> + async { + do! Async.Sleep 50 // wait for events from initial project check + checker.Caches.TcIntermediate.OnEvent cacheTcIntermediateEvents.Enqueue + checker.Caches.DependencyGraph.OnEvent cacheGraphConstructionEvents.Enqueue + }) + updateFile "B" updatePublicSurface + checkFile "E" expectOk + } |> ignore + + let intermediateTypeChecks = + cacheTcIntermediateEvents + |> Seq.groupBy (fun (_e, (l, _k, _)) -> l) + |> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList) + |> Seq.toList + + let graphConstructions = + cacheGraphConstructionEvents + |> Seq.groupBy (fun (_e, (l, _k, _)) -> l) + |> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList) + |> Seq.toList + + Assert.Equal(["FileE.fs", [Started; Finished]], graphConstructions) + Assert.Equal(["FileE.fs", [Started; Finished]], intermediateTypeChecks) + +[] +let ``Changing impl files doesn't invalidate cache when they have signatures`` () = + let project = SyntheticProject.Create( + { sourceFile "A" [] with SignatureFile = AutoGenerated }, + { sourceFile "B" ["A"] with SignatureFile = AutoGenerated }, + { sourceFile "C" ["B"] with SignatureFile = AutoGenerated }) + + let cacheEvents = ConcurrentQueue() + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + updateFile "A" updatePublicSurface + checkFile "C" expectOk + withChecker (fun checker -> + async { + do! Async.Sleep 50 // wait for events from initial project check + checker.Caches.TcIntermediate.OnEvent cacheEvents.Enqueue + }) + updateFile "A" updateInternal + checkFile "C" expectOk + } |> ignore + + let intermediateTypeChecks = + cacheEvents + |> Seq.groupBy (fun (_e, (l, _k, _)) -> l) + |> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList) + |> Seq.toList + + Assert.Equal([], intermediateTypeChecks) + +[] +let ``Changing impl file doesn't invalidate an in-memory referenced project`` () = + let library = SyntheticProject.Create("library", { sourceFile "A" [] with SignatureFile = AutoGenerated }) + + let project = { + SyntheticProject.Create("project", sourceFile "B" ["A"] ) + with DependsOn = [library] } + + let cacheEvents = ConcurrentQueue() + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + checkFile "B" expectOk + withChecker (fun checker -> + async { + do! Async.Sleep 50 // wait for events from initial project check + checker.Caches.TcIntermediate.OnEvent cacheEvents.Enqueue + }) + updateFile "A" updateInternal + checkFile "B" expectOk + } |> ignore + + let intermediateTypeChecks = + cacheEvents + |> Seq.groupBy (fun (_e, (l, _k, _)) -> l) + |> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList) + |> Seq.toList + + Assert.Equal([], intermediateTypeChecks) + + +[] +[] +[] +let ``Multi-project`` signatureFiles = + + let sigFile = if signatureFiles then AutoGenerated else No + + let library = SyntheticProject.Create("library", + { sourceFile "LibA" [] + with + Source = "let f (x: int) = x" + SignatureFile = sigFile }, + { sourceFile "LibB" ["LibA"] with SignatureFile = sigFile }, + { sourceFile "LibC" ["LibA"] with SignatureFile = sigFile }, + { sourceFile "LibD" ["LibB"; "LibC"] with SignatureFile = sigFile } + ) + + let project = + { SyntheticProject.Create("app", + sourceFile "A" ["LibB"], + sourceFile "B" ["A"; "LibB"], + sourceFile "C" ["A"; "LibC"], + sourceFile "D" ["A"; "LibD"] + ) + with DependsOn = [library] } + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + updateFile "LibA" updatePublicSurface + checkFile "D" expectOk + } + + + +type ProjectAction = Get | Modify of (SyntheticProject -> SyntheticProject) +type ProjectModificaiton = Update of int | Add | Remove +type ProjectRequest = ProjectAction * AsyncReplyChannel + +type FuzzingEvent = StartedChecking | FinishedChecking of bool | AbortedChecking of string | ModifiedImplFile | ModifiedSigFile + +[] +type SignatureFiles = Yes = 1 | No = 2 | Some = 3 + +let fuzzingTest seed (project: SyntheticProject) = task { + let rng = System.Random seed + + let checkingThreads = 3 + let maxModificationDelayMs = 10 + let maxCheckingDelayMs = 20 + //let runTimeMs = 30000 + let signatureFileModificationProbability = 0.25 + let modificationLoopIterations = 10 + let checkingLoopIterations = 5 + + let minCheckingTimeoutMs = 0 + let maxCheckingTimeoutMs = 300 + + let builder = ProjectWorkflowBuilder(project, useTransparentCompiler = true, autoStart = false) + let checker = builder.Checker + + // Force creation and caching of options + do! SaveAndCheckProject project checker |> Async.Ignore + + let projectAgent = MailboxProcessor.Start(fun (inbox: MailboxProcessor) -> + let rec loop project = + async { + let! action, reply = inbox.Receive() + let! project = + match action with + | Modify f -> async { + let p = f project + do! saveProject p false checker + return p } + | Get -> async.Return project + reply.Reply project + return! loop project + } + loop project) + + let getProject () = + projectAgent.PostAndAsyncReply(pair Get) + + let modifyProject f = + projectAgent.PostAndAsyncReply(pair(Modify f)) |> Async.Ignore + + let modificationProbabilities = [ + Update 1, 80 + Update 2, 5 + Update 10, 5 + //Add, 2 + //Remove, 1 + ] + + let modificationPicker = [| + for op, prob in modificationProbabilities do + for _ in 1 .. prob do + op + |] + + let addComment s = $"{s}\n\n// {rng.NextDouble()}" + let modifyImplFile f = { f with ExtraSource = f.ExtraSource |> addComment } + let modifySigFile f = { f with SignatureFile = Custom (f.SignatureFile.CustomText |> addComment) } + + let getRandomItem (xs: 'x array) = xs[rng.Next(0, xs.Length)] + + let getRandomModification () = modificationPicker |> getRandomItem + + let getRandomFile (project: SyntheticProject) = project.GetAllFiles() |> List.toArray |> getRandomItem + + let log = new ThreadLocal<_>((fun () -> ResizeArray<_>()), true) + + let exceptions = ConcurrentBag() + + let modificationLoop _ = task { + for _ in 1 .. modificationLoopIterations do + do! Task.Delay (rng.Next maxModificationDelayMs) + let modify project = + match getRandomModification() with + | Update n -> + + use _ = Activity.start "Update" [||] + let files = Set [ for _ in 1..n -> getRandomFile project |> snd ] + (project, files) + ||> Seq.fold (fun p file -> + let fileId = file.Id + let project, file = project.FindInAllProjects fileId + let opName, f = + if file.HasSignatureFile && rng.NextDouble() < signatureFileModificationProbability + then ModifiedSigFile, modifySigFile + else ModifiedImplFile, modifyImplFile + log.Value.Add (DateTime.Now.Ticks, opName, $"{project.Name} / {fileId}") + p |> updateFileInAnyProject fileId f) + | Add + | Remove -> + // TODO: + project + do! modifyProject modify + } + + let checkingLoop n _ = task { + for _ in 1 .. checkingLoopIterations do + let! project = getProject() + let p, file = project |> getRandomFile + + let timeout = rng.Next(minCheckingTimeoutMs, maxCheckingTimeoutMs) + + log.Value.Add (DateTime.Now.Ticks, StartedChecking, $"Loop #{n} {file.Id} ({timeout} ms timeout)") + let ct = new CancellationTokenSource() + ct.CancelAfter(timeout) + let job = Async.StartAsTask(checker |> checkFile file.Id p, cancellationToken = ct.Token) + try + use _ = Activity.start "Check" [||] + + let! parseResult, checkResult = job + log.Value.Add (DateTime.Now.Ticks, FinishedChecking (match checkResult with FSharpCheckFileAnswer.Succeeded _ -> true | _ -> false), $"Loop #{n} {file.Id}") + expectOk (parseResult, checkResult) () + with ex -> + let message = + match ex with + | :? AggregateException as e -> + match e.InnerException with + | :? GraphProcessingException as e -> $"GPE: {e.InnerException.Message}" + | _ -> e.Message + | _ -> ex.Message + log.Value.Add (DateTime.Now.Ticks, AbortedChecking (message), $"Loop #{n} {file.Id} %A{ex}") + if ex.Message <> "A task was canceled." then exceptions.Add ex + + do! Task.Delay (rng.Next maxCheckingDelayMs) + } + + use _tracerProvider = + Sdk.CreateTracerProviderBuilder() + .AddSource("fsc") + .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(serviceName="F# Fuzzing", serviceVersion = "1")) + .AddJaegerExporter() + .Build() + + use _ = Activity.start $"Fuzzing {project.Name}" [ Activity.Tags.project, project.Name; "seed", seed.ToString() ] + + do! task { + let threads = + seq { + modificationLoop CancellationToken.None + // ignore modificationLoop + for n in 1..checkingThreads do + checkingLoop n CancellationToken.None + } + + try + let! _x = threads |> Seq.skip 1 |> Task.WhenAll + () + with + | e -> + let _log = log.Values |> Seq.collect id |> Seq.sortBy p13 |> Seq.toArray + failwith $"Seed: {seed}\nException: %A{e}" + } + let log = log.Values |> Seq.collect id |> Seq.sortBy p13 |> Seq.toArray + + let _stats = log |> Array.groupBy (p23) |> Array.map (fun (op, xs) -> op, xs.Length) |> Map + + let _errors = _stats |> Map.toSeq |> Seq.filter (fst >> function AbortedChecking ex when ex <> "A task was canceled." -> true | _ -> false) |> Seq.toArray + + let _exceptions = exceptions + + Assert.Equal>([||], _errors) + + //Assert.Equal>(Map.empty, _stats) + + builder.DeleteProjectDir() +} + + +[] +[] +[] +[] +let Fuzzing signatureFiles = + + let seed = 1106087513 + let rng = System.Random(int seed) + + let fileCount = 30 + let maxDepsPerFile = 3 + + let fileName i = sprintf $"F%03d{i}" + + //let extraCode = __SOURCE_DIRECTORY__ ++ ".." ++ ".." ++ ".." ++ "src" ++ "Compiler" ++ "Utilities" ++ "EditDistance.fs" |> File.ReadAllLines |> Seq.skip 5 |> String.concat "\n" + let extraCode = "" + + let files = + [| for i in 1 .. fileCount do + let name = fileName i + let deps = [ + for _ in 1 .. maxDepsPerFile do + if i > 1 then + fileName <| rng.Next(1, i) ] + let signature = + match signatureFiles with + | SignatureFiles.Yes -> AutoGenerated + | SignatureFiles.Some when rng.NextDouble() < 0.5 -> AutoGenerated + | _ -> No + + { sourceFile name deps + with + SignatureFile = signature + ExtraSource = extraCode } + |] + + let initialProject = SyntheticProject.Create(files) + + let builder = ProjectWorkflowBuilder(initialProject, useTransparentCompiler = true, autoStart = false) + let checker = builder.Checker + + let initialProject = initialProject |> absorbAutoGeneratedSignatures checker |> Async.RunSynchronously + + fuzzingTest seed initialProject + + +let reposDir = __SOURCE_DIRECTORY__ ++ ".." ++ ".." ++ ".." ++ ".." +let giraffeDir = reposDir ++ "Giraffe" ++ "src" ++ "Giraffe" |> Path.GetFullPath +let giraffeTestsDir = reposDir ++ "Giraffe" ++ "tests" ++ "Giraffe.Tests" |> Path.GetFullPath +let giraffeSignaturesDir = reposDir ++ "giraffe-signatures" ++ "src" ++ "Giraffe" |> Path.GetFullPath +let giraffeSignaturesTestsDir = reposDir ++ "giraffe-signatures" ++ "tests" ++ "Giraffe.Tests" |> Path.GetFullPath + + +type GiraffeTheoryAttribute() = + inherit Xunit.TheoryAttribute() + do + if not (Directory.Exists giraffeDir) then + do base.Skip <- $"Giraffe not found ({giraffeDir}). You can get it here: https://github.com/giraffe-fsharp/Giraffe" + if not (Directory.Exists giraffeSignaturesDir) then + do base.Skip <- $"Giraffe (with signatures) not found ({giraffeSignaturesDir}). You can get it here: https://github.com/nojaf/Giraffe/tree/signatures" + +[] +[] +[] +let GiraffeFuzzing signatureFiles = + let seed = System.Random().Next() + //let seed = 1044159179 + + let giraffeDir = if signatureFiles then giraffeSignaturesDir else giraffeDir + let giraffeTestsDir = if signatureFiles then giraffeSignaturesTestsDir else giraffeTestsDir + + let giraffeProject = SyntheticProject.CreateFromRealProject giraffeDir + let giraffeProject = { giraffeProject with OtherOptions = "--nowarn:FS3520"::giraffeProject.OtherOptions } + + let testsProject = SyntheticProject.CreateFromRealProject giraffeTestsDir + let testsProject = + { testsProject + with + OtherOptions = "--nowarn:FS3520"::testsProject.OtherOptions + DependsOn = [ giraffeProject ] + NugetReferences = giraffeProject.NugetReferences @ testsProject.NugetReferences + } + + fuzzingTest seed testsProject + + + +[] +[] +[] +let ``File moving test`` signatureFiles = + let giraffeDir = if signatureFiles then giraffeSignaturesDir else giraffeDir + let giraffeProject = SyntheticProject.CreateFromRealProject giraffeDir + let giraffeProject = { giraffeProject with OtherOptions = "--nowarn:FS3520"::giraffeProject.OtherOptions } + + giraffeProject.Workflow { + // clearCache -- for better tracing + checkFile "Json" expectOk + moveFile "Json" 1 Down + checkFile "Json" expectOk + } + + +[] +[] +let ``What happens if bootrstapInfoStatic needs to be recomputed`` _ = + + let giraffeProject = SyntheticProject.CreateFromRealProject giraffeSignaturesDir + let giraffeProject = { giraffeProject with OtherOptions = "--nowarn:FS3520"::giraffeProject.OtherOptions } + + giraffeProject.Workflow { + updateFile "Helpers" (fun f -> { f with SignatureFile = Custom (f.SignatureFile.CustomText + "\n") }) + checkFile "EndpointRouting" expectOk + withChecker (fun checker -> + async { + checker.Caches.BootstrapInfoStatic.Clear() + checker.Caches.BootstrapInfo.Clear() + checker.Caches.FrameworkImports.Clear() + ignore checker + return () + }) + updateFile "Core" (fun f -> { f with SignatureFile = Custom (f.SignatureFile.CustomText + "\n") }) + checkFile "EndpointRouting" expectOk + } + + +module ParsedInputHashing = + + let source = """ + +type T = { A: int; B: string } + +module Stuff = + + // Some comment + let f x = x + 75 +""" + + let getParseResult source = + let fileName, snapshot, checker = singleFileChecker source + checker.ParseFile(fileName, snapshot) |> Async.RunSynchronously + + //[] + let ``Hash stays the same when whitespace changes`` () = + + //let parseResult = getParseResult source + + //let hash = parseResult.ParseTree |> parsedInputHash |> BitConverter.ToString + + //let parseResult2 = getParseResult (source + "\n \n") + + //let hash2 = parseResult2.ParseTree |> parsedInputHash |> BitConverter.ToString + + //Assert.Equal(hash, hash2) + + () \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/DiscriminatedUnionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/DiscriminatedUnionTests.fs index 194284177cc..a8b1e0cb404 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/DiscriminatedUnionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/DiscriminatedUnionTests.fs @@ -17,6 +17,20 @@ if foo.IsBar then failwith "Should not be Bar" |> compileExeAndRun |> shouldSucceed + [] + let ``Simple Is* discriminated union properties are not visible for a single case union`` () = + Fsx """ +type Foo = Bar of string +let foo = Foo.Bar "hi" +if not foo.IsBar then failwith "Should be Bar" + + """ + |> withLangVersionPreview + |> typecheck + |> shouldFail + |> withDiagnostics [Error 39, Line 4, Col 12, Line 4, Col 17, "The type 'Foo' does not define the field, constructor or member 'IsBar'. Maybe you want one of the following: + Bar"] + [] let ``Simple Is* discriminated union property satisfies SRTP constraint`` () = Fsx """ diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ExtensionMethodTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ExtensionMethodTests.fs index 510ac830ae4..60f902e9ef5 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ExtensionMethodTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ExtensionMethodTests.fs @@ -648,3 +648,40 @@ module M = |> withReferences [ csharp ] fsharp |> compile |> shouldSucceed + + [] + let ``F# CSharpStyleExtensionMethod consumed in F#`` () = + let producer = + FSharp + """ +namespace Producer + +open System.Runtime.CompilerServices + +type WidgetBuilder<'msg, 'marker>() = class end + +type IMarkerOne = interface end + +// Commenting out [] breaks +//[] +type WidgetBuilderExtensions = + [] + static member inline one(this: WidgetBuilder<'msg, #IMarkerOne>) = this +""" + |> withLangVersion80 + |> withName "FSLibProducer" + + let fsharp2 = + FSharp + """ +namespace Consumer + +open Producer + +module FSLibConsumer = + let x = WidgetBuilder().one() +""" + |> withName "FSLibConsumer" + |> withReferences [ producer ] + + fsharp2 |> compile |> shouldSucceed diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs index 2f90f8963c6..982ae0c820b 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs @@ -440,5 +440,6 @@ let typedSeq = |> typecheck |> shouldFail |> withErrorCode 30 - |> withDiagnosticMessageMatches "Value restriction. The value 'typedSeq' has been inferred to have generic type" + |> withDiagnosticMessageMatches "Value restriction: The value 'typedSeq' has an inferred generic type" + |> withDiagnosticMessageMatches "val typedSeq: '_a seq" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/MissingDiagnostic.fs b/tests/FSharp.Compiler.ComponentTests/Signatures/MissingDiagnostic.fs index 55181649b03..15b2ae61df0 100644 --- a/tests/FSharp.Compiler.ComponentTests/Signatures/MissingDiagnostic.fs +++ b/tests/FSharp.Compiler.ComponentTests/Signatures/MissingDiagnostic.fs @@ -27,28 +27,34 @@ let ``Compile gives errors`` () = but here has type 'char' ") -[] -let ``Type check project with signature file doesn't get the diagnostic`` () = +[] +[] +[] +let ``Type check project with signature file doesn't get the diagnostic`` useTransparentCompiler = Fsi signature |> withAdditionalSourceFile (FsSource implementation) - |> typecheckProject false + |> typecheckProject false useTransparentCompiler |> fun projectResults -> projectResults.Diagnostics |> ignore Assert.False (projectResults.Diagnostics |> Array.isEmpty) -[] -let ``Type check project without signature file does get the diagnostic`` () = +[] +[] +[] +let ``Type check project without signature file does get the diagnostic`` useTransparentCompiler = Fs implementation - |> typecheckProject false + |> typecheckProject false useTransparentCompiler |> fun projectResults -> projectResults.Diagnostics |> ignore Assert.False (projectResults.Diagnostics |> Array.isEmpty) -[] -let ``Enabling enablePartialTypeChecking = true doesn't change the problem`` () = +[] +[] +[] +let ``Enabling enablePartialTypeChecking = true doesn't change the problem`` useTransparentCompiler = Fsi signature |> withAdditionalSourceFile (FsSource implementation) - |> typecheckProject true + |> typecheckProject true useTransparentCompiler |> fun projectResults -> projectResults.Diagnostics |> ignore Assert.False (projectResults.Diagnostics |> Array.isEmpty) \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/Scenarios.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/Scenarios.fs index c75aed594c3..80f7caecafb 100644 --- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/Scenarios.fs +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/Scenarios.fs @@ -800,4 +800,114 @@ printfn "Hello" """ Set.empty ] + scenario + "Nameof module with namespace" + [ + sourceFile + "A.fs" + """ +namespace X.Y.Z + +module Foo = + let x = 2 +""" + Set.empty + sourceFile + "B.fs" + """ +namespace X.Y.Z + +module Point = + let y = nameof Foo +""" + (set [| 0 |]) + ] + scenario + "Nameof module without namespace" + [ + sourceFile + "A.fs" + """ +module Foo + +let x = 2 +""" + Set.empty + sourceFile + "B.fs" + """ +module Point + +let y = nameof Foo +""" + (set [| 0 |]) + ] + scenario + "Single module name should always be checked, regardless of own namespace" + [ + sourceFile "X.fs" "namespace X.Y" Set.empty + sourceFile + "A.fs" + """ +module Foo + +let x = 2 +""" + Set.empty + sourceFile + "B.fs" + """ +namespace X.Y + +type T() = + let _ = nameof Foo +""" + (set [| 1 |]) + ] + scenario + "nameof pattern" + [ + sourceFile "A.fs" "module Foo" Set.empty + sourceFile + "B.fs" + """ +module Bar + +do + match "" with + | nameof Foo -> () + | _ -> () +""" + (set [| 0 |]) + ] + scenario + "parentheses around module name in nameof pattern" + [ + sourceFile "A.fs" "module Foo" Set.empty + sourceFile + "B.fs" + """ +module Bar + +do + match "" with + | nameof ((Foo)) -> () + | _ -> () +""" + (set [| 0 |]) + ] + + scenario + "parentheses around module name in nameof expression" + [ + sourceFile "A.fs" "module Foo" Set.empty + sourceFile + "B.fs" + """ +module Bar + +let _ = nameof ((Foo)) +""" + (set [| 0 |]) + ] ] \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TypedTreeGraph.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TypedTreeGraph.fs index 9e25c623532..c4680870efc 100644 --- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TypedTreeGraph.fs +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TypedTreeGraph.fs @@ -140,7 +140,7 @@ let ``Create Graph from typed tree`` (projectArgumentsFilePath: string) = graphFromTypedTree |> Graph.map (fun n -> n,files.[n].File) - |> Graph.serialiseToMermaid $"{fileName}.typed-tree.deps.md" + |> Graph.writeMermaidToFile $"{fileName}.typed-tree.deps.md" let collectAllDeps (graph: Graph) = (Map.empty, [ 0 .. (sourceFiles.Length - 1) ]) @@ -161,7 +161,7 @@ let ``Create Graph from typed tree`` (projectArgumentsFilePath: string) = graphFromHeuristic |> Graph.map (fun n -> n, files.[n].File) - |> Graph.serialiseToMermaid $"{fileName}.heuristic-tree.deps.md" + |> Graph.writeMermaidToFile $"{fileName}.heuristic-tree.deps.md" let heuristicMap = collectAllDeps graphFromHeuristic diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TyparNameTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TyparNameTests.fs index 118ea134ff3..339fa1e2629 100644 --- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TyparNameTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TyparNameTests.fs @@ -14,7 +14,7 @@ module TyparNameTests = (additionalFile: SourceCodeFileKind) : string array = let typeCheckResult = - cUnit |> withAdditionalSourceFile additionalFile |> typecheckProject false + cUnit |> withAdditionalSourceFile additionalFile |> typecheckProject false false assert (Array.isEmpty typeCheckResult.Diagnostics) diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl index 15b58c9aea1..954fca3437d 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl @@ -318,8 +318,6 @@ FSharp.Compiler.AbstractIL.IL+ILAttributesStored: System.String ToString() FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(ILCallingConv) FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(System.Object) FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean IsCallconv -FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean get_IsCallconv() FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILArgConvention Item2 FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILArgConvention get_Item2() FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILCallingConv Instance @@ -2078,7 +2076,7 @@ FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: FSharp.Compiler.Symbols. FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String ToString() FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String[] DependencyFiles FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String[] get_DependencyFiles() -FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker Create(Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.DateTime],Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[System.Object,System.IntPtr,System.Int32]]]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.DocumentSource], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker Create(Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.DateTime],Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[System.Object,System.IntPtr,System.Int32]]]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.DocumentSource], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker Instance FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker get_Instance() FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpProjectOptions GetProjectOptionsFromCommandLineArgs(System.String, System.String[], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) @@ -2089,14 +2087,19 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Int32 get_ActualCheckFileCount() FSharp.Compiler.CodeAnalysis.FSharpChecker: Int32 get_ActualParseFileCount() FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer] CheckFileInProject(FSharp.Compiler.CodeAnalysis.FSharpParseFileResults, System.String, Int32, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults] ParseAndCheckProject(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults] ParseAndCheckProject(FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] GetBackgroundParseResultsForFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] ParseFile(System.String, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpParsingOptions, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] ParseFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] ParseFileInProject(System.String, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] CheckFileInProjectAllowingStaleCachedResults(FSharp.Compiler.CodeAnalysis.FSharpParseFileResults, System.String, Int32, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.SemanticClassificationView]] GetBackgroundSemanticClassificationForFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.SemanticClassificationView]] GetBackgroundSemanticClassificationForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] NotifyFileChanged(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] NotifyProjectCleaned(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Collections.Generic.IEnumerable`1[FSharp.Compiler.Text.Range]] FindBackgroundReferencesInFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Collections.Generic.IEnumerable`1[FSharp.Compiler.Text.Range]] FindBackgroundReferencesInFile(System.String, FSharpProjectSnapshot, FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] ParseAndCheckFileInProject(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] ParseAndCheckFileInProject(System.String, Int32, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults]] GetBackgroundCheckResultsForFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]]] GetProjectOptionsFromScript(System.String, FSharp.Compiler.Text.ISourceText, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.String[]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Int64], Microsoft.FSharp.Core.FSharpOption`1[System.String]) @@ -2117,6 +2120,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeA FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromProjectOptions(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.Tokenization.FSharpTokenInfo[],FSharp.Compiler.Tokenization.FSharpTokenizerLexState] TokenizeLine(System.String, FSharp.Compiler.Tokenization.FSharpTokenizerLexState) FSharp.Compiler.CodeAnalysis.FSharpChecker: Void ClearCache(System.Collections.Generic.IEnumerable`1[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Void ClearCache(System.Collections.Generic.IEnumerable`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier], Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Void ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients() FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateAll() FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateConfiguration(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) @@ -2334,6 +2338,76 @@ FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String get_baggage() FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String get_itemSpec() FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String itemSpec FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: Void .ctor(System.String, Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.String],System.String], System.String) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: Boolean Equals(System.Object) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: Boolean IsSignatureFile +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: Boolean get_IsSignatureFile() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: FSharpFileSnapshot Create(System.String, System.String, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Threading.Tasks.Task`1[FSharp.Compiler.Text.ISourceTextNew]]) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: FSharpFileSnapshot CreateFromFileSystem(System.String) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: Int32 GetHashCode() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: System.String FileName +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: System.String GetFileName() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: System.String Version +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: System.String get_FileName() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: System.String get_Version() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: System.Threading.Tasks.Task`1[FSharp.Compiler.Text.ISourceTextNew] GetSource() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: Void .ctor(System.String, System.String, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Threading.Tasks.Task`1[FSharp.Compiler.Text.ISourceTextNew]]) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Boolean Equals(FSharpProjectIdentifier) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Boolean Equals(System.Object) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Boolean Equals(System.Object, System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: FSharpProjectIdentifier NewFSharpProjectIdentifier(System.String, System.String) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Int32 CompareTo(FSharpProjectIdentifier) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Int32 CompareTo(System.Object) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Int32 CompareTo(System.Object, System.Collections.IComparer) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Int32 GetHashCode() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Int32 GetHashCode(System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Int32 Tag +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Int32 get_Tag() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: System.String ToString() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: System.String get_outputFileName() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: System.String get_projectFileName() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: System.String outputFileName +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: System.String projectFileName +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: FSharpProjectIdentifier Identifier +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: FSharpProjectIdentifier get_Identifier() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: FSharpProjectSnapshot Create(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot], Boolean, Boolean, System.DateTime, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet], Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Text.Range,System.String,System.String]], Microsoft.FSharp.Core.FSharpOption`1[System.Int64]) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: FSharpProjectSnapshot Replace(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot]) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot] FromOptions(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot] FromOptions(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions,Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot]]], Microsoft.FSharp.Core.FSharpOption`1[System.Collections.Generic.Dictionary`2[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions,FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot]]) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot] FromOptions(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, System.String, Int32, FSharp.Compiler.Text.ISourceText) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: System.String Label +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: System.String get_Label() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: Boolean Equals(System.Object) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: FSharpProjectSnapshot get_options() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: FSharpProjectSnapshot options +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: FSharpReferencedProjectSnapshot CreateFSharp(System.String, FSharpProjectSnapshot) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: FSharpReferencedProjectSnapshot NewFSharpReference(System.String, FSharpProjectSnapshot) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: Int32 GetHashCode() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: Int32 Tag +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: Int32 get_Tag() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: System.String OutputFile +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: System.String ToString() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: System.String get_OutputFile() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: System.String get_projectOutputFile() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: System.String projectOutputFile +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Boolean Equals(ReferenceOnDisk) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Boolean Equals(System.Object) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Boolean Equals(System.Object, System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Int32 CompareTo(ReferenceOnDisk) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Int32 CompareTo(System.Object) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Int32 CompareTo(System.Object, System.Collections.IComparer) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Int32 GetHashCode() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Int32 GetHashCode(System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: System.DateTime LastModified +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: System.DateTime get_LastModified() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: System.String Path +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: System.String ToString() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: System.String get_Path() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Void .ctor(System.String, System.DateTime) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot: FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot +FSharp.Compiler.CodeAnalysis.ProjectSnapshot: FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier +FSharp.Compiler.CodeAnalysis.ProjectSnapshot: FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot +FSharp.Compiler.CodeAnalysis.ProjectSnapshot: FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot +FSharp.Compiler.CodeAnalysis.ProjectSnapshot: FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk FSharp.Compiler.CompilerEnvironment: Boolean IsCheckerSupportedSubcategory(System.String) FSharp.Compiler.CompilerEnvironment: Boolean IsCompilable(System.String) FSharp.Compiler.CompilerEnvironment: Boolean IsScriptFile(System.String) @@ -4271,8 +4345,6 @@ FSharp.Compiler.EditorServices.ToolTipElementData: Void .ctor(Microsoft.FSharp.C FSharp.Compiler.EditorServices.ToolTipText: Boolean Equals(FSharp.Compiler.EditorServices.ToolTipText) FSharp.Compiler.EditorServices.ToolTipText: Boolean Equals(System.Object) FSharp.Compiler.EditorServices.ToolTipText: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.EditorServices.ToolTipText: Boolean IsToolTipText -FSharp.Compiler.EditorServices.ToolTipText: Boolean get_IsToolTipText() FSharp.Compiler.EditorServices.ToolTipText: FSharp.Compiler.EditorServices.ToolTipText NewToolTipText(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.EditorServices.ToolTipElement]) FSharp.Compiler.EditorServices.ToolTipText: Int32 GetHashCode() FSharp.Compiler.EditorServices.ToolTipText: Int32 GetHashCode(System.Collections.IEqualityComparer) @@ -4292,7 +4364,6 @@ FSharp.Compiler.EditorServices.TupledArgumentLocation: Int32 GetHashCode() FSharp.Compiler.EditorServices.TupledArgumentLocation: Int32 GetHashCode(System.Collections.IEqualityComparer) FSharp.Compiler.EditorServices.TupledArgumentLocation: System.String ToString() FSharp.Compiler.EditorServices.TupledArgumentLocation: Void .ctor(Boolean, FSharp.Compiler.Text.Range) -FSharp.Compiler.EditorServices.UnnecessaryParentheses: Microsoft.FSharp.Control.FSharpAsync`1[System.Collections.Generic.IEnumerable`1[FSharp.Compiler.Text.Range]] getUnnecessaryParentheses(Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.String], FSharp.Compiler.Syntax.ParsedInput) FSharp.Compiler.EditorServices.UnresolvedSymbol: Boolean Equals(FSharp.Compiler.EditorServices.UnresolvedSymbol) FSharp.Compiler.EditorServices.UnresolvedSymbol: Boolean Equals(System.Object) FSharp.Compiler.EditorServices.UnresolvedSymbol: Boolean Equals(System.Object, System.Collections.IEqualityComparer) @@ -4316,8 +4387,6 @@ FSharp.Compiler.EditorServices.XmlDocParser: Microsoft.FSharp.Collections.FSharp FSharp.Compiler.EditorServices.XmlDocable: Boolean Equals(FSharp.Compiler.EditorServices.XmlDocable) FSharp.Compiler.EditorServices.XmlDocable: Boolean Equals(System.Object) FSharp.Compiler.EditorServices.XmlDocable: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.EditorServices.XmlDocable: Boolean IsXmlDocable -FSharp.Compiler.EditorServices.XmlDocable: Boolean get_IsXmlDocable() FSharp.Compiler.EditorServices.XmlDocable: FSharp.Compiler.EditorServices.XmlDocable NewXmlDocable(Int32, Int32, Microsoft.FSharp.Collections.FSharpList`1[System.String]) FSharp.Compiler.EditorServices.XmlDocable: Int32 CompareTo(FSharp.Compiler.EditorServices.XmlDocable) FSharp.Compiler.EditorServices.XmlDocable: Int32 CompareTo(System.Object) @@ -5556,8 +5625,6 @@ FSharp.Compiler.Syntax.DebugPointAtInOrTo: System.String ToString() FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean Equals(FSharp.Compiler.Syntax.DebugPointAtLeafExpr) FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean Equals(System.Object) FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean IsYes -FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean get_IsYes() FSharp.Compiler.Syntax.DebugPointAtLeafExpr: FSharp.Compiler.Syntax.DebugPointAtLeafExpr NewYes(FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.DebugPointAtLeafExpr: FSharp.Compiler.Text.Range Item FSharp.Compiler.Syntax.DebugPointAtLeafExpr: FSharp.Compiler.Text.Range get_Item() @@ -5692,8 +5759,6 @@ FSharp.Compiler.Syntax.Ident: System.String ToString() FSharp.Compiler.Syntax.Ident: System.String get_idText() FSharp.Compiler.Syntax.Ident: System.String idText FSharp.Compiler.Syntax.Ident: Void .ctor(System.String, FSharp.Compiler.Text.Range) -FSharp.Compiler.Syntax.ParsedHashDirective: Boolean IsParsedHashDirective -FSharp.Compiler.Syntax.ParsedHashDirective: Boolean get_IsParsedHashDirective() FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Syntax.ParsedHashDirective NewParsedHashDirective(System.String, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirectiveArgument], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Text.Range range @@ -5732,8 +5797,6 @@ FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: FSharp.Compiler.Text.Range g FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: Int32 Tag FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: Int32 get_Tag() FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: System.String ToString() -FSharp.Compiler.Syntax.ParsedImplFile: Boolean IsParsedImplFile -FSharp.Compiler.Syntax.ParsedImplFile: Boolean get_IsParsedImplFile() FSharp.Compiler.Syntax.ParsedImplFile: FSharp.Compiler.Syntax.ParsedImplFile NewParsedImplFile(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirective], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedImplFileFragment]) FSharp.Compiler.Syntax.ParsedImplFile: Int32 Tag FSharp.Compiler.Syntax.ParsedImplFile: Int32 get_Tag() @@ -5785,11 +5848,9 @@ FSharp.Compiler.Syntax.ParsedImplFileFragment: Int32 get_Tag() FSharp.Compiler.Syntax.ParsedImplFileFragment: System.String ToString() FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsExe FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsLastCompiland -FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsParsedImplFileInput FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsScript FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsExe() FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsLastCompiland() -FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsParsedImplFileInput() FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsScript() FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_isScript() FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean isScript @@ -5853,8 +5914,12 @@ FSharp.Compiler.Syntax.ParsedInput: Microsoft.FSharp.Collections.FSharpSet`1[Sys FSharp.Compiler.Syntax.ParsedInput: System.String FileName FSharp.Compiler.Syntax.ParsedInput: System.String ToString() FSharp.Compiler.Syntax.ParsedInput: System.String get_FileName() -FSharp.Compiler.Syntax.ParsedScriptInteraction: Boolean IsDefinitions -FSharp.Compiler.Syntax.ParsedScriptInteraction: Boolean get_IsDefinitions() +FSharp.Compiler.Syntax.ParsedInputModule: Boolean exists(Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode],Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SyntaxNode,System.Boolean]], FSharp.Compiler.Text.Position, FSharp.Compiler.Syntax.ParsedInput) +FSharp.Compiler.Syntax.ParsedInputModule: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Syntax.SyntaxNode,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode]]] tryNode(FSharp.Compiler.Text.Position, FSharp.Compiler.Syntax.ParsedInput) +FSharp.Compiler.Syntax.ParsedInputModule: Microsoft.FSharp.Core.FSharpOption`1[T] tryPickLast[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode],Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SyntaxNode,Microsoft.FSharp.Core.FSharpOption`1[T]]], FSharp.Compiler.Text.Position, FSharp.Compiler.Syntax.ParsedInput) +FSharp.Compiler.Syntax.ParsedInputModule: Microsoft.FSharp.Core.FSharpOption`1[T] tryPick[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode],Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SyntaxNode,Microsoft.FSharp.Core.FSharpOption`1[T]]], FSharp.Compiler.Text.Position, FSharp.Compiler.Syntax.ParsedInput) +FSharp.Compiler.Syntax.ParsedInputModule: State foldWhile[State](Microsoft.FSharp.Core.FSharpFunc`2[State,Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode],Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SyntaxNode,Microsoft.FSharp.Core.FSharpOption`1[State]]]], State, FSharp.Compiler.Syntax.ParsedInput) +FSharp.Compiler.Syntax.ParsedInputModule: State fold[State](Microsoft.FSharp.Core.FSharpFunc`2[State,Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode],Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SyntaxNode,State]]], State, FSharp.Compiler.Syntax.ParsedInput) FSharp.Compiler.Syntax.ParsedScriptInteraction: FSharp.Compiler.Syntax.ParsedScriptInteraction NewDefinitions(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.ParsedScriptInteraction: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.ParsedScriptInteraction: FSharp.Compiler.Text.Range range @@ -5863,8 +5928,6 @@ FSharp.Compiler.Syntax.ParsedScriptInteraction: Int32 get_Tag() FSharp.Compiler.Syntax.ParsedScriptInteraction: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl] defns FSharp.Compiler.Syntax.ParsedScriptInteraction: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl] get_defns() FSharp.Compiler.Syntax.ParsedScriptInteraction: System.String ToString() -FSharp.Compiler.Syntax.ParsedSigFile: Boolean IsParsedSigFile -FSharp.Compiler.Syntax.ParsedSigFile: Boolean get_IsParsedSigFile() FSharp.Compiler.Syntax.ParsedSigFile: FSharp.Compiler.Syntax.ParsedSigFile NewParsedSigFile(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirective], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedSigFileFragment]) FSharp.Compiler.Syntax.ParsedSigFile: Int32 Tag FSharp.Compiler.Syntax.ParsedSigFile: Int32 get_Tag() @@ -5914,8 +5977,6 @@ FSharp.Compiler.Syntax.ParsedSigFileFragment: FSharp.Compiler.Syntax.ParsedSigFi FSharp.Compiler.Syntax.ParsedSigFileFragment: Int32 Tag FSharp.Compiler.Syntax.ParsedSigFileFragment: Int32 get_Tag() FSharp.Compiler.Syntax.ParsedSigFileFragment: System.String ToString() -FSharp.Compiler.Syntax.ParsedSigFileInput: Boolean IsParsedSigFileInput -FSharp.Compiler.Syntax.ParsedSigFileInput: Boolean get_IsParsedSigFileInput() FSharp.Compiler.Syntax.ParsedSigFileInput: FSharp.Compiler.Syntax.ParsedSigFileInput NewParsedSigFileInput(System.String, FSharp.Compiler.Syntax.QualifiedNameOfFile, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ScopedPragma], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirective], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleOrNamespaceSig], FSharp.Compiler.SyntaxTrivia.ParsedSigFileInputTrivia, Microsoft.FSharp.Collections.FSharpSet`1[System.String]) FSharp.Compiler.Syntax.ParsedSigFileInput: FSharp.Compiler.Syntax.QualifiedNameOfFile QualifiedName FSharp.Compiler.Syntax.ParsedSigFileInput: FSharp.Compiler.Syntax.QualifiedNameOfFile get_QualifiedName() @@ -5988,8 +6049,6 @@ FSharp.Compiler.Syntax.PrettyNaming: System.String FormatAndOtherOverloadsString FSharp.Compiler.Syntax.PrettyNaming: System.String FsiDynamicModulePrefix FSharp.Compiler.Syntax.PrettyNaming: System.String NormalizeIdentifierBackticks(System.String) FSharp.Compiler.Syntax.PrettyNaming: System.String get_FsiDynamicModulePrefix() -FSharp.Compiler.Syntax.QualifiedNameOfFile: Boolean IsQualifiedNameOfFile -FSharp.Compiler.Syntax.QualifiedNameOfFile: Boolean get_IsQualifiedNameOfFile() FSharp.Compiler.Syntax.QualifiedNameOfFile: FSharp.Compiler.Syntax.Ident Id FSharp.Compiler.Syntax.QualifiedNameOfFile: FSharp.Compiler.Syntax.Ident Item FSharp.Compiler.Syntax.QualifiedNameOfFile: FSharp.Compiler.Syntax.Ident get_Id() @@ -6005,8 +6064,6 @@ FSharp.Compiler.Syntax.QualifiedNameOfFile: System.String get_Text() FSharp.Compiler.Syntax.ScopedPragma: Boolean Equals(FSharp.Compiler.Syntax.ScopedPragma) FSharp.Compiler.Syntax.ScopedPragma: Boolean Equals(System.Object) FSharp.Compiler.Syntax.ScopedPragma: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.Syntax.ScopedPragma: Boolean IsWarningOff -FSharp.Compiler.Syntax.ScopedPragma: Boolean get_IsWarningOff() FSharp.Compiler.Syntax.ScopedPragma: FSharp.Compiler.Syntax.ScopedPragma NewWarningOff(FSharp.Compiler.Text.Range, Int32) FSharp.Compiler.Syntax.ScopedPragma: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.ScopedPragma: FSharp.Compiler.Text.Range range @@ -6020,9 +6077,7 @@ FSharp.Compiler.Syntax.ScopedPragma: System.String ToString() FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(FSharp.Compiler.Syntax.SeqExprOnly) FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(System.Object) FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.Syntax.SeqExprOnly: Boolean IsSeqExprOnly FSharp.Compiler.Syntax.SeqExprOnly: Boolean Item -FSharp.Compiler.Syntax.SeqExprOnly: Boolean get_IsSeqExprOnly() FSharp.Compiler.Syntax.SeqExprOnly: Boolean get_Item() FSharp.Compiler.Syntax.SeqExprOnly: FSharp.Compiler.Syntax.SeqExprOnly NewSeqExprOnly(Boolean) FSharp.Compiler.Syntax.SeqExprOnly: Int32 CompareTo(FSharp.Compiler.Syntax.SeqExprOnly) @@ -6065,8 +6120,6 @@ FSharp.Compiler.Syntax.SynAccess: Int32 GetHashCode(System.Collections.IEquality FSharp.Compiler.Syntax.SynAccess: Int32 Tag FSharp.Compiler.Syntax.SynAccess: Int32 get_Tag() FSharp.Compiler.Syntax.SynAccess: System.String ToString() -FSharp.Compiler.Syntax.SynArgInfo: Boolean IsSynArgInfo -FSharp.Compiler.Syntax.SynArgInfo: Boolean get_IsSynArgInfo() FSharp.Compiler.Syntax.SynArgInfo: Boolean get_optional() FSharp.Compiler.Syntax.SynArgInfo: Boolean optional FSharp.Compiler.Syntax.SynArgInfo: FSharp.Compiler.Syntax.SynArgInfo NewSynArgInfo(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]) @@ -6123,8 +6176,6 @@ FSharp.Compiler.Syntax.SynAttributeList: Microsoft.FSharp.Collections.FSharpList FSharp.Compiler.Syntax.SynAttributeList: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttribute] get_Attributes() FSharp.Compiler.Syntax.SynAttributeList: System.String ToString() FSharp.Compiler.Syntax.SynAttributeList: Void .ctor(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttribute], FSharp.Compiler.Text.Range) -FSharp.Compiler.Syntax.SynBinding: Boolean IsSynBinding -FSharp.Compiler.Syntax.SynBinding: Boolean get_IsSynBinding() FSharp.Compiler.Syntax.SynBinding: Boolean get_isInline() FSharp.Compiler.Syntax.SynBinding: Boolean get_isMutable() FSharp.Compiler.Syntax.SynBinding: Boolean isInline @@ -6188,8 +6239,6 @@ FSharp.Compiler.Syntax.SynBindingKind: Int32 GetHashCode(System.Collections.IEqu FSharp.Compiler.Syntax.SynBindingKind: Int32 Tag FSharp.Compiler.Syntax.SynBindingKind: Int32 get_Tag() FSharp.Compiler.Syntax.SynBindingKind: System.String ToString() -FSharp.Compiler.Syntax.SynBindingReturnInfo: Boolean IsSynBindingReturnInfo -FSharp.Compiler.Syntax.SynBindingReturnInfo: Boolean get_IsSynBindingReturnInfo() FSharp.Compiler.Syntax.SynBindingReturnInfo: FSharp.Compiler.Syntax.SynBindingReturnInfo NewSynBindingReturnInfo(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.SyntaxTrivia.SynBindingReturnInfoTrivia) FSharp.Compiler.Syntax.SynBindingReturnInfo: FSharp.Compiler.Syntax.SynType get_typeName() FSharp.Compiler.Syntax.SynBindingReturnInfo: FSharp.Compiler.Syntax.SynType typeName @@ -6224,8 +6273,6 @@ FSharp.Compiler.Syntax.SynByteStringKind: Int32 GetHashCode(System.Collections.I FSharp.Compiler.Syntax.SynByteStringKind: Int32 Tag FSharp.Compiler.Syntax.SynByteStringKind: Int32 get_Tag() FSharp.Compiler.Syntax.SynByteStringKind: System.String ToString() -FSharp.Compiler.Syntax.SynComponentInfo: Boolean IsSynComponentInfo -FSharp.Compiler.Syntax.SynComponentInfo: Boolean get_IsSynComponentInfo() FSharp.Compiler.Syntax.SynComponentInfo: Boolean get_preferPostfix() FSharp.Compiler.Syntax.SynComponentInfo: Boolean preferPostfix FSharp.Compiler.Syntax.SynComponentInfo: FSharp.Compiler.Syntax.SynComponentInfo NewSynComponentInfo(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynTyparDecls], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynTypeConstraint], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Xml.PreXmlDoc, Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range) @@ -6425,8 +6472,6 @@ FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Text.Range Range(FSharp.Compile FSharp.Compiler.Syntax.SynConst: Int32 Tag FSharp.Compiler.Syntax.SynConst: Int32 get_Tag() FSharp.Compiler.Syntax.SynConst: System.String ToString() -FSharp.Compiler.Syntax.SynEnumCase: Boolean IsSynEnumCase -FSharp.Compiler.Syntax.SynEnumCase: Boolean get_IsSynEnumCase() FSharp.Compiler.Syntax.SynEnumCase: FSharp.Compiler.Syntax.SynEnumCase NewSynEnumCase(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynIdent, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynEnumCaseTrivia) FSharp.Compiler.Syntax.SynEnumCase: FSharp.Compiler.Syntax.SynExpr get_valueExpr() FSharp.Compiler.Syntax.SynEnumCase: FSharp.Compiler.Syntax.SynExpr valueExpr @@ -6445,8 +6490,6 @@ 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.SynExceptionDefn: Boolean IsSynExceptionDefn -FSharp.Compiler.Syntax.SynExceptionDefn: Boolean get_IsSynExceptionDefn() 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 FSharp.Compiler.Syntax.SynExceptionDefn: FSharp.Compiler.Syntax.SynExceptionDefnRepr get_exnRepr() @@ -6461,8 +6504,6 @@ FSharp.Compiler.Syntax.SynExceptionDefn: Microsoft.FSharp.Collections.FSharpList FSharp.Compiler.Syntax.SynExceptionDefn: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_withKeyword() FSharp.Compiler.Syntax.SynExceptionDefn: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] withKeyword FSharp.Compiler.Syntax.SynExceptionDefn: System.String ToString() -FSharp.Compiler.Syntax.SynExceptionDefnRepr: Boolean IsSynExceptionDefnRepr -FSharp.Compiler.Syntax.SynExceptionDefnRepr: Boolean get_IsSynExceptionDefnRepr() FSharp.Compiler.Syntax.SynExceptionDefnRepr: FSharp.Compiler.Syntax.SynExceptionDefnRepr NewSynExceptionDefnRepr(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynUnionCase, Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident]], FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExceptionDefnRepr: FSharp.Compiler.Syntax.SynUnionCase caseName FSharp.Compiler.Syntax.SynExceptionDefnRepr: FSharp.Compiler.Syntax.SynUnionCase get_caseName() @@ -6481,8 +6522,6 @@ FSharp.Compiler.Syntax.SynExceptionDefnRepr: Microsoft.FSharp.Core.FSharpOption` FSharp.Compiler.Syntax.SynExceptionDefnRepr: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident]] get_longId() FSharp.Compiler.Syntax.SynExceptionDefnRepr: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident]] longId FSharp.Compiler.Syntax.SynExceptionDefnRepr: System.String ToString() -FSharp.Compiler.Syntax.SynExceptionSig: Boolean IsSynExceptionSig -FSharp.Compiler.Syntax.SynExceptionSig: Boolean get_IsSynExceptionSig() FSharp.Compiler.Syntax.SynExceptionSig: FSharp.Compiler.Syntax.SynExceptionDefnRepr exnRepr FSharp.Compiler.Syntax.SynExceptionSig: FSharp.Compiler.Syntax.SynExceptionDefnRepr get_exnRepr() FSharp.Compiler.Syntax.SynExceptionSig: FSharp.Compiler.Syntax.SynExceptionSig NewSynExceptionSig(FSharp.Compiler.Syntax.SynExceptionDefnRepr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberSig], FSharp.Compiler.Text.Range) @@ -7417,8 +7456,6 @@ FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Text.Range get_RangeWithoutAnyEx FSharp.Compiler.Syntax.SynExpr: Int32 Tag FSharp.Compiler.Syntax.SynExpr: Int32 get_Tag() FSharp.Compiler.Syntax.SynExpr: System.String ToString() -FSharp.Compiler.Syntax.SynExprAndBang: Boolean IsSynExprAndBang -FSharp.Compiler.Syntax.SynExprAndBang: Boolean get_IsSynExprAndBang() FSharp.Compiler.Syntax.SynExprAndBang: Boolean get_isFromSource() FSharp.Compiler.Syntax.SynExprAndBang: Boolean get_isUse() FSharp.Compiler.Syntax.SynExprAndBang: Boolean isFromSource @@ -7437,8 +7474,7 @@ FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynExprAndBang: Int32 Tag FSharp.Compiler.Syntax.SynExprAndBang: Int32 get_Tag() FSharp.Compiler.Syntax.SynExprAndBang: System.String ToString() -FSharp.Compiler.Syntax.SynExprRecordField: Boolean IsSynExprRecordField -FSharp.Compiler.Syntax.SynExprRecordField: Boolean get_IsSynExprRecordField() +FSharp.Compiler.Syntax.SynExprModule: Boolean shouldBeParenthesizedInContext(Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynExpr) FSharp.Compiler.Syntax.SynExprRecordField: FSharp.Compiler.Syntax.SynExprRecordField NewSynExprRecordField(System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr], Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]) FSharp.Compiler.Syntax.SynExprRecordField: Int32 Tag FSharp.Compiler.Syntax.SynExprRecordField: Int32 get_Tag() @@ -7451,8 +7487,6 @@ FSharp.Compiler.Syntax.SynExprRecordField: Microsoft.FSharp.Core.FSharpOption`1[ FSharp.Compiler.Syntax.SynExprRecordField: System.String ToString() FSharp.Compiler.Syntax.SynExprRecordField: System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean] fieldName FSharp.Compiler.Syntax.SynExprRecordField: System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean] get_fieldName() -FSharp.Compiler.Syntax.SynField: Boolean IsSynField -FSharp.Compiler.Syntax.SynField: Boolean get_IsSynField() FSharp.Compiler.Syntax.SynField: Boolean get_isMutable() FSharp.Compiler.Syntax.SynField: Boolean get_isStatic() FSharp.Compiler.Syntax.SynField: Boolean isMutable @@ -7477,8 +7511,6 @@ FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Com FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] accessibility FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] get_accessibility() FSharp.Compiler.Syntax.SynField: System.String ToString() -FSharp.Compiler.Syntax.SynIdent: Boolean IsSynIdent -FSharp.Compiler.Syntax.SynIdent: Boolean get_IsSynIdent() FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.Ident get_ident() FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.Ident ident FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.SynIdent NewSynIdent(FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia]) @@ -7487,8 +7519,6 @@ FSharp.Compiler.Syntax.SynIdent: Int32 get_Tag() FSharp.Compiler.Syntax.SynIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia] get_trivia() FSharp.Compiler.Syntax.SynIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia] trivia FSharp.Compiler.Syntax.SynIdent: System.String ToString() -FSharp.Compiler.Syntax.SynInterfaceImpl: Boolean IsSynInterfaceImpl -FSharp.Compiler.Syntax.SynInterfaceImpl: Boolean get_IsSynInterfaceImpl() FSharp.Compiler.Syntax.SynInterfaceImpl: FSharp.Compiler.Syntax.SynInterfaceImpl NewSynInterfaceImpl(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynBinding], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynInterfaceImpl: FSharp.Compiler.Syntax.SynType get_interfaceTy() FSharp.Compiler.Syntax.SynInterfaceImpl: FSharp.Compiler.Syntax.SynType interfaceTy @@ -7525,9 +7555,7 @@ FSharp.Compiler.Syntax.SynInterpolatedStringPart: FSharp.Compiler.Syntax.SynInte FSharp.Compiler.Syntax.SynInterpolatedStringPart: Int32 Tag FSharp.Compiler.Syntax.SynInterpolatedStringPart: Int32 get_Tag() FSharp.Compiler.Syntax.SynInterpolatedStringPart: System.String ToString() -FSharp.Compiler.Syntax.SynLongIdent: Boolean IsSynLongIdent FSharp.Compiler.Syntax.SynLongIdent: Boolean ThereIsAnExtraDotAtTheEnd -FSharp.Compiler.Syntax.SynLongIdent: Boolean get_IsSynLongIdent() FSharp.Compiler.Syntax.SynLongIdent: Boolean get_ThereIsAnExtraDotAtTheEnd() FSharp.Compiler.Syntax.SynLongIdent: FSharp.Compiler.Syntax.SynLongIdent NewSynLongIdent(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia]]) FSharp.Compiler.Syntax.SynLongIdent: FSharp.Compiler.Text.Range Range @@ -7553,8 +7581,6 @@ FSharp.Compiler.Syntax.SynLongIdent: Microsoft.FSharp.Collections.FSharpList`1[M FSharp.Compiler.Syntax.SynLongIdent: System.String ToString() FSharp.Compiler.Syntax.SynLongIdentHelpers: FSharp.Compiler.Syntax.SynLongIdent LongIdentWithDots(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range]) FSharp.Compiler.Syntax.SynLongIdentHelpers: System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident],Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range]] |LongIdentWithDots|(FSharp.Compiler.Syntax.SynLongIdent) -FSharp.Compiler.Syntax.SynMatchClause: Boolean IsSynMatchClause -FSharp.Compiler.Syntax.SynMatchClause: Boolean get_IsSynMatchClause() FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.DebugPointAtTarget debugPoint FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.DebugPointAtTarget get_debugPoint() FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.SynExpr get_resultExpr() @@ -7708,8 +7734,8 @@ FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: Microsoft.FSharp.Core.FSharpO FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding] get_memberDefnForSet() FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding] memberDefnForGet FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding] memberDefnForSet -FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.Syntax.SynSimplePats ctorArgs -FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.Syntax.SynSimplePats get_ctorArgs() +FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.Syntax.SynPat ctorArgs +FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.Syntax.SynPat get_ctorArgs() FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.SyntaxTrivia.SynMemberDefnImplicitCtorTrivia get_trivia() FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.SyntaxTrivia.SynMemberDefnImplicitCtorTrivia trivia FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.Text.Range get_range() @@ -7809,7 +7835,7 @@ FSharp.Compiler.Syntax.SynMemberDefn: Boolean get_IsValField() FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewAbstractSlot(FSharp.Compiler.Syntax.SynValSig, FSharp.Compiler.Syntax.SynMemberFlags, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnAbstractSlotTrivia) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewAutoProperty(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Boolean, FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynType], FSharp.Compiler.Syntax.SynMemberKind, FSharp.Compiler.Syntax.SynMemberFlags, FSharp.Compiler.Syntax.SynMemberFlags, FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnAutoPropertyTrivia) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewGetSetMember(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia) -FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitCtor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynSimplePats, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnImplicitCtorTrivia) +FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitCtor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynPat, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnImplicitCtorTrivia) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitInherit(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewInherit(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewInterface(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn]], FSharp.Compiler.Text.Range) @@ -8052,8 +8078,6 @@ FSharp.Compiler.Syntax.SynModuleDecl: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynModuleDecl: Int32 Tag FSharp.Compiler.Syntax.SynModuleDecl: Int32 get_Tag() FSharp.Compiler.Syntax.SynModuleDecl: System.String ToString() -FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean IsSynModuleOrNamespace -FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean get_IsSynModuleOrNamespace() FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean get_isRecursive() FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean isRecursive FSharp.Compiler.Syntax.SynModuleOrNamespace: FSharp.Compiler.Syntax.SynModuleOrNamespace NewSynModuleOrNamespace(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], Boolean, FSharp.Compiler.Syntax.SynModuleOrNamespaceKind, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl], FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynModuleOrNamespaceTrivia) @@ -8112,8 +8136,6 @@ FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: Int32 GetHashCode(System.Collec FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: Int32 Tag FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: Int32 get_Tag() FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: System.String ToString() -FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean IsSynModuleOrNamespaceSig -FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean get_IsSynModuleOrNamespaceSig() FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean get_isRecursive() FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean isRecursive FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: FSharp.Compiler.Syntax.SynModuleOrNamespaceKind get_kind() @@ -8466,6 +8488,7 @@ FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynPat: Int32 Tag FSharp.Compiler.Syntax.SynPat: Int32 get_Tag() FSharp.Compiler.Syntax.SynPat: System.String ToString() +FSharp.Compiler.Syntax.SynPatModule: Boolean shouldBeParenthesizedInContext(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynPat) FSharp.Compiler.Syntax.SynRationalConst+Integer: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynRationalConst+Integer: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynRationalConst+Integer: Int32 get_value() @@ -8514,8 +8537,6 @@ FSharp.Compiler.Syntax.SynRationalConst: FSharp.Compiler.Syntax.SynRationalConst FSharp.Compiler.Syntax.SynRationalConst: Int32 Tag FSharp.Compiler.Syntax.SynRationalConst: Int32 get_Tag() FSharp.Compiler.Syntax.SynRationalConst: System.String ToString() -FSharp.Compiler.Syntax.SynReturnInfo: Boolean IsSynReturnInfo -FSharp.Compiler.Syntax.SynReturnInfo: Boolean get_IsSynReturnInfo() FSharp.Compiler.Syntax.SynReturnInfo: FSharp.Compiler.Syntax.SynReturnInfo NewSynReturnInfo(System.Tuple`2[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Syntax.SynArgInfo], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynReturnInfo: FSharp.Compiler.Text.Range Range FSharp.Compiler.Syntax.SynReturnInfo: FSharp.Compiler.Text.Range get_Range() @@ -8589,8 +8610,6 @@ FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: FSharp.Compiler.Syntax.Syn FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: Int32 Tag FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: Int32 get_Tag() FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: System.String ToString() -FSharp.Compiler.Syntax.SynSimplePats: Boolean IsSimplePats -FSharp.Compiler.Syntax.SynSimplePats: Boolean get_IsSimplePats() FSharp.Compiler.Syntax.SynSimplePats: FSharp.Compiler.Syntax.SynSimplePats NewSimplePats(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynSimplePat], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynSimplePats: FSharp.Compiler.Text.Range Range FSharp.Compiler.Syntax.SynSimplePats: FSharp.Compiler.Text.Range get_Range() @@ -8681,8 +8700,6 @@ FSharp.Compiler.Syntax.SynTupleTypeSegment: FSharp.Compiler.Text.Range get_Range FSharp.Compiler.Syntax.SynTupleTypeSegment: Int32 Tag FSharp.Compiler.Syntax.SynTupleTypeSegment: Int32 get_Tag() FSharp.Compiler.Syntax.SynTupleTypeSegment: System.String ToString() -FSharp.Compiler.Syntax.SynTypar: Boolean IsSynTypar -FSharp.Compiler.Syntax.SynTypar: Boolean get_IsSynTypar() FSharp.Compiler.Syntax.SynTypar: Boolean get_isCompGen() FSharp.Compiler.Syntax.SynTypar: Boolean isCompGen FSharp.Compiler.Syntax.SynTypar: FSharp.Compiler.Syntax.Ident get_ident() @@ -8695,8 +8712,6 @@ FSharp.Compiler.Syntax.SynTypar: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynTypar: Int32 Tag FSharp.Compiler.Syntax.SynTypar: Int32 get_Tag() FSharp.Compiler.Syntax.SynTypar: System.String ToString() -FSharp.Compiler.Syntax.SynTyparDecl: Boolean IsSynTyparDecl -FSharp.Compiler.Syntax.SynTyparDecl: Boolean get_IsSynTyparDecl() FSharp.Compiler.Syntax.SynTyparDecl: FSharp.Compiler.Syntax.SynTypar get_typar() FSharp.Compiler.Syntax.SynTyparDecl: FSharp.Compiler.Syntax.SynTypar typar FSharp.Compiler.Syntax.SynTyparDecl: FSharp.Compiler.Syntax.SynTyparDecl NewSynTyparDecl(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynTypar, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynType], FSharp.Compiler.SyntaxTrivia.SynTyparDeclTrivia) @@ -9129,8 +9144,6 @@ FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynTypeConstraint: Int32 Tag FSharp.Compiler.Syntax.SynTypeConstraint: Int32 get_Tag() FSharp.Compiler.Syntax.SynTypeConstraint: System.String ToString() -FSharp.Compiler.Syntax.SynTypeDefn: Boolean IsSynTypeDefn -FSharp.Compiler.Syntax.SynTypeDefn: Boolean get_IsSynTypeDefn() FSharp.Compiler.Syntax.SynTypeDefn: FSharp.Compiler.Syntax.SynComponentInfo get_typeInfo() FSharp.Compiler.Syntax.SynTypeDefn: FSharp.Compiler.Syntax.SynComponentInfo typeInfo FSharp.Compiler.Syntax.SynTypeDefn: FSharp.Compiler.Syntax.SynTypeDefn NewSynTypeDefn(FSharp.Compiler.Syntax.SynComponentInfo, FSharp.Compiler.Syntax.SynTypeDefnRepr, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberDefn], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynTypeDefnTrivia) @@ -9247,8 +9260,6 @@ FSharp.Compiler.Syntax.SynTypeDefnRepr: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynTypeDefnRepr: Int32 Tag FSharp.Compiler.Syntax.SynTypeDefnRepr: Int32 get_Tag() FSharp.Compiler.Syntax.SynTypeDefnRepr: System.String ToString() -FSharp.Compiler.Syntax.SynTypeDefnSig: Boolean IsSynTypeDefnSig -FSharp.Compiler.Syntax.SynTypeDefnSig: Boolean get_IsSynTypeDefnSig() FSharp.Compiler.Syntax.SynTypeDefnSig: FSharp.Compiler.Syntax.SynComponentInfo get_typeInfo() FSharp.Compiler.Syntax.SynTypeDefnSig: FSharp.Compiler.Syntax.SynComponentInfo typeInfo FSharp.Compiler.Syntax.SynTypeDefnSig: FSharp.Compiler.Syntax.SynTypeDefnSig NewSynTypeDefnSig(FSharp.Compiler.Syntax.SynComponentInfo, FSharp.Compiler.Syntax.SynTypeDefnSigRepr, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberSig], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynTypeDefnSigTrivia) @@ -9318,8 +9329,8 @@ FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Collectio FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.Syntax.SynValSig,FSharp.Compiler.Syntax.SynMemberFlags]] slotsigs FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]]] get_inherits() FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]]] inherits -FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynSimplePats] get_implicitCtorSynPats() -FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynSimplePats] implicitCtorSynPats +FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynPat] get_implicitCtorSynPats() +FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynPat] implicitCtorSynPats FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+LibraryOnlyILAssembly: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+LibraryOnlyILAssembly: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+LibraryOnlyILAssembly: System.Object get_ilType() @@ -9370,7 +9381,7 @@ FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: Boolean get_IsTypeAbbrev() FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: Boolean get_IsUnion() FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewEnum(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynEnumCase], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewException(FSharp.Compiler.Syntax.SynExceptionDefnRepr) -FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewGeneral(FSharp.Compiler.Syntax.SynTypeDefnKind, Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]]], Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.Syntax.SynValSig,FSharp.Compiler.Syntax.SynMemberFlags]], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynField], Boolean, Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynSimplePats], FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewGeneral(FSharp.Compiler.Syntax.SynTypeDefnKind, Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]]], Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.Syntax.SynValSig,FSharp.Compiler.Syntax.SynMemberFlags]], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynField], Boolean, Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynPat], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewLibraryOnlyILAssembly(System.Object, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewNone(FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewRecord(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynField], FSharp.Compiler.Text.Range) @@ -9390,8 +9401,6 @@ FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Text.Range get_Ran FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: Int32 Tag FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: Int32 get_Tag() FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: System.String ToString() -FSharp.Compiler.Syntax.SynUnionCase: Boolean IsSynUnionCase -FSharp.Compiler.Syntax.SynUnionCase: Boolean get_IsSynUnionCase() FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynIdent get_ident() FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynIdent ident FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynUnionCase NewSynUnionCase(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynIdent, FSharp.Compiler.Syntax.SynUnionCaseKind, FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynUnionCaseTrivia) @@ -9432,8 +9441,6 @@ FSharp.Compiler.Syntax.SynUnionCaseKind: FSharp.Compiler.Syntax.SynUnionCaseKind FSharp.Compiler.Syntax.SynUnionCaseKind: Int32 Tag FSharp.Compiler.Syntax.SynUnionCaseKind: Int32 get_Tag() FSharp.Compiler.Syntax.SynUnionCaseKind: System.String ToString() -FSharp.Compiler.Syntax.SynValData: Boolean IsSynValData -FSharp.Compiler.Syntax.SynValData: Boolean get_IsSynValData() FSharp.Compiler.Syntax.SynValData: FSharp.Compiler.Syntax.SynValData NewSynValData(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberFlags], FSharp.Compiler.Syntax.SynValInfo, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]) FSharp.Compiler.Syntax.SynValData: FSharp.Compiler.Syntax.SynValInfo SynValInfo FSharp.Compiler.Syntax.SynValData: FSharp.Compiler.Syntax.SynValInfo get_SynValInfo() @@ -9446,8 +9453,6 @@ FSharp.Compiler.Syntax.SynValData: Microsoft.FSharp.Core.FSharpOption`1[FSharp.C FSharp.Compiler.Syntax.SynValData: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberFlags] get_memberFlags() FSharp.Compiler.Syntax.SynValData: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberFlags] memberFlags FSharp.Compiler.Syntax.SynValData: System.String ToString() -FSharp.Compiler.Syntax.SynValInfo: Boolean IsSynValInfo -FSharp.Compiler.Syntax.SynValInfo: Boolean get_IsSynValInfo() FSharp.Compiler.Syntax.SynValInfo: FSharp.Compiler.Syntax.SynArgInfo get_returnInfo() FSharp.Compiler.Syntax.SynValInfo: FSharp.Compiler.Syntax.SynArgInfo returnInfo FSharp.Compiler.Syntax.SynValInfo: FSharp.Compiler.Syntax.SynValInfo NewSynValInfo(Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynArgInfo]], FSharp.Compiler.Syntax.SynArgInfo) @@ -9460,8 +9465,6 @@ FSharp.Compiler.Syntax.SynValInfo: Microsoft.FSharp.Collections.FSharpList`1[Mic FSharp.Compiler.Syntax.SynValInfo: Microsoft.FSharp.Collections.FSharpList`1[System.String] ArgNames FSharp.Compiler.Syntax.SynValInfo: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_ArgNames() FSharp.Compiler.Syntax.SynValInfo: System.String ToString() -FSharp.Compiler.Syntax.SynValSig: Boolean IsSynValSig -FSharp.Compiler.Syntax.SynValSig: Boolean get_IsSynValSig() FSharp.Compiler.Syntax.SynValSig: Boolean get_isInline() FSharp.Compiler.Syntax.SynValSig: Boolean get_isMutable() FSharp.Compiler.Syntax.SynValSig: Boolean isInline @@ -9496,9 +9499,7 @@ FSharp.Compiler.Syntax.SynValSig: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Co FSharp.Compiler.Syntax.SynValSig: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr] get_synExpr() FSharp.Compiler.Syntax.SynValSig: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr] synExpr FSharp.Compiler.Syntax.SynValSig: System.String ToString() -FSharp.Compiler.Syntax.SynValTyparDecls: Boolean IsSynValTyparDecls FSharp.Compiler.Syntax.SynValTyparDecls: Boolean canInfer -FSharp.Compiler.Syntax.SynValTyparDecls: Boolean get_IsSynValTyparDecls() FSharp.Compiler.Syntax.SynValTyparDecls: Boolean get_canInfer() FSharp.Compiler.Syntax.SynValTyparDecls: FSharp.Compiler.Syntax.SynValTyparDecls NewSynValTyparDecls(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynTyparDecls], Boolean) FSharp.Compiler.Syntax.SynValTyparDecls: Int32 Tag @@ -9605,9 +9606,12 @@ FSharp.Compiler.Syntax.SyntaxNode: FSharp.Compiler.Syntax.SyntaxNode+SynTypeDefn FSharp.Compiler.Syntax.SyntaxNode: FSharp.Compiler.Syntax.SyntaxNode+SynTypeDefnSig FSharp.Compiler.Syntax.SyntaxNode: FSharp.Compiler.Syntax.SyntaxNode+SynValSig FSharp.Compiler.Syntax.SyntaxNode: FSharp.Compiler.Syntax.SyntaxNode+Tags +FSharp.Compiler.Syntax.SyntaxNode: FSharp.Compiler.Text.Range Range +FSharp.Compiler.Syntax.SyntaxNode: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SyntaxNode: Int32 Tag FSharp.Compiler.Syntax.SyntaxNode: Int32 get_Tag() FSharp.Compiler.Syntax.SyntaxNode: System.String ToString() +FSharp.Compiler.Syntax.SyntaxNodeModule: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList] |Attributes|(FSharp.Compiler.Syntax.SyntaxNode) FSharp.Compiler.Syntax.SyntaxTraversal: Microsoft.FSharp.Core.FSharpOption`1[T] Traverse[T](FSharp.Compiler.Text.Position, FSharp.Compiler.Syntax.ParsedInput, FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitAttributeApplication(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynAttributeList) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitBinding(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynBinding,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynBinding) @@ -9627,7 +9631,7 @@ FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOptio FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitPat(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynPat,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynPat) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitRecordDefn(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynField], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitRecordField(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynLongIdent]) -FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitSimplePats(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynSimplePat]) +FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitSimplePats(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynPat) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitType(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynType,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynType) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitTypeAbbrev(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitUnionDefn(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynUnionCase], FSharp.Compiler.Text.Range) @@ -10344,6 +10348,7 @@ FSharp.Compiler.Text.ISourceText: System.String GetSubTextFromRange(FSharp.Compi FSharp.Compiler.Text.ISourceText: System.String GetSubTextString(Int32, Int32) FSharp.Compiler.Text.ISourceText: System.Tuple`2[System.Int32,System.Int32] GetLastCharacterPosition() FSharp.Compiler.Text.ISourceText: Void CopyTo(Int32, Char[], Int32, Int32) +FSharp.Compiler.Text.ISourceTextNew: System.Collections.Immutable.ImmutableArray`1[System.Byte] GetChecksum() FSharp.Compiler.Text.Line: Int32 fromZ(Int32) FSharp.Compiler.Text.Line: Int32 toZ(Int32) FSharp.Compiler.Text.NavigableTaggedText: FSharp.Compiler.Text.Range Range @@ -10423,6 +10428,8 @@ FSharp.Compiler.Text.RangeModule: System.Tuple`2[System.String,System.Tuple`2[Sy FSharp.Compiler.Text.RangeModule: System.Tuple`2[System.Tuple`2[System.Int32,System.Int32],System.Tuple`2[System.Int32,System.Int32]] toZ(FSharp.Compiler.Text.Range) FSharp.Compiler.Text.RangeModule: Void outputRange(System.IO.TextWriter, FSharp.Compiler.Text.Range) FSharp.Compiler.Text.SourceText: FSharp.Compiler.Text.ISourceText ofString(System.String) +FSharp.Compiler.Text.SourceTextNew: FSharp.Compiler.Text.ISourceTextNew ofISourceText(FSharp.Compiler.Text.ISourceText) +FSharp.Compiler.Text.SourceTextNew: FSharp.Compiler.Text.ISourceTextNew ofString(System.String) FSharp.Compiler.Text.TaggedText: FSharp.Compiler.Text.TextTag Tag FSharp.Compiler.Text.TaggedText: FSharp.Compiler.Text.TextTag get_Tag() FSharp.Compiler.Text.TaggedText: System.String Text diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl index 15b58c9aea1..954fca3437d 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl @@ -318,8 +318,6 @@ FSharp.Compiler.AbstractIL.IL+ILAttributesStored: System.String ToString() FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(ILCallingConv) FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(System.Object) FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean IsCallconv -FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean get_IsCallconv() FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILArgConvention Item2 FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILArgConvention get_Item2() FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILCallingConv Instance @@ -2078,7 +2076,7 @@ FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: FSharp.Compiler.Symbols. FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String ToString() FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String[] DependencyFiles FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String[] get_DependencyFiles() -FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker Create(Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.DateTime],Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[System.Object,System.IntPtr,System.Int32]]]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.DocumentSource], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker Create(Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.DateTime],Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[System.Object,System.IntPtr,System.Int32]]]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.DocumentSource], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker Instance FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker get_Instance() FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpProjectOptions GetProjectOptionsFromCommandLineArgs(System.String, System.String[], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) @@ -2089,14 +2087,19 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Int32 get_ActualCheckFileCount() FSharp.Compiler.CodeAnalysis.FSharpChecker: Int32 get_ActualParseFileCount() FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer] CheckFileInProject(FSharp.Compiler.CodeAnalysis.FSharpParseFileResults, System.String, Int32, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults] ParseAndCheckProject(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults] ParseAndCheckProject(FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] GetBackgroundParseResultsForFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] ParseFile(System.String, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpParsingOptions, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] ParseFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] ParseFileInProject(System.String, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] CheckFileInProjectAllowingStaleCachedResults(FSharp.Compiler.CodeAnalysis.FSharpParseFileResults, System.String, Int32, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.SemanticClassificationView]] GetBackgroundSemanticClassificationForFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.SemanticClassificationView]] GetBackgroundSemanticClassificationForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] NotifyFileChanged(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] NotifyProjectCleaned(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Collections.Generic.IEnumerable`1[FSharp.Compiler.Text.Range]] FindBackgroundReferencesInFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Collections.Generic.IEnumerable`1[FSharp.Compiler.Text.Range]] FindBackgroundReferencesInFile(System.String, FSharpProjectSnapshot, FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] ParseAndCheckFileInProject(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] ParseAndCheckFileInProject(System.String, Int32, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults]] GetBackgroundCheckResultsForFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]]] GetProjectOptionsFromScript(System.String, FSharp.Compiler.Text.ISourceText, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.String[]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Int64], Microsoft.FSharp.Core.FSharpOption`1[System.String]) @@ -2117,6 +2120,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeA FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromProjectOptions(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.Tokenization.FSharpTokenInfo[],FSharp.Compiler.Tokenization.FSharpTokenizerLexState] TokenizeLine(System.String, FSharp.Compiler.Tokenization.FSharpTokenizerLexState) FSharp.Compiler.CodeAnalysis.FSharpChecker: Void ClearCache(System.Collections.Generic.IEnumerable`1[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Void ClearCache(System.Collections.Generic.IEnumerable`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier], Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Void ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients() FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateAll() FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateConfiguration(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) @@ -2334,6 +2338,76 @@ FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String get_baggage() FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String get_itemSpec() FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String itemSpec FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: Void .ctor(System.String, Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.String],System.String], System.String) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: Boolean Equals(System.Object) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: Boolean IsSignatureFile +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: Boolean get_IsSignatureFile() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: FSharpFileSnapshot Create(System.String, System.String, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Threading.Tasks.Task`1[FSharp.Compiler.Text.ISourceTextNew]]) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: FSharpFileSnapshot CreateFromFileSystem(System.String) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: Int32 GetHashCode() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: System.String FileName +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: System.String GetFileName() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: System.String Version +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: System.String get_FileName() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: System.String get_Version() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: System.Threading.Tasks.Task`1[FSharp.Compiler.Text.ISourceTextNew] GetSource() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot: Void .ctor(System.String, System.String, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Threading.Tasks.Task`1[FSharp.Compiler.Text.ISourceTextNew]]) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Boolean Equals(FSharpProjectIdentifier) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Boolean Equals(System.Object) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Boolean Equals(System.Object, System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: FSharpProjectIdentifier NewFSharpProjectIdentifier(System.String, System.String) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Int32 CompareTo(FSharpProjectIdentifier) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Int32 CompareTo(System.Object) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Int32 CompareTo(System.Object, System.Collections.IComparer) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Int32 GetHashCode() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Int32 GetHashCode(System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Int32 Tag +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: Int32 get_Tag() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: System.String ToString() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: System.String get_outputFileName() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: System.String get_projectFileName() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: System.String outputFileName +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier: System.String projectFileName +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: FSharpProjectIdentifier Identifier +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: FSharpProjectIdentifier get_Identifier() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: FSharpProjectSnapshot Create(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot], Boolean, Boolean, System.DateTime, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet], Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Text.Range,System.String,System.String]], Microsoft.FSharp.Core.FSharpOption`1[System.Int64]) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: FSharpProjectSnapshot Replace(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot]) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot] FromOptions(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot] FromOptions(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions,Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot]]], Microsoft.FSharp.Core.FSharpOption`1[System.Collections.Generic.Dictionary`2[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions,FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot]]) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot] FromOptions(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, System.String, Int32, FSharp.Compiler.Text.ISourceText) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: System.String Label +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot: System.String get_Label() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: Boolean Equals(System.Object) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: FSharpProjectSnapshot get_options() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: FSharpProjectSnapshot options +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: FSharpReferencedProjectSnapshot CreateFSharp(System.String, FSharpProjectSnapshot) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: FSharpReferencedProjectSnapshot NewFSharpReference(System.String, FSharpProjectSnapshot) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: Int32 GetHashCode() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: Int32 Tag +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: Int32 get_Tag() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: System.String OutputFile +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: System.String ToString() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: System.String get_OutputFile() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: System.String get_projectOutputFile() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot: System.String projectOutputFile +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Boolean Equals(ReferenceOnDisk) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Boolean Equals(System.Object) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Boolean Equals(System.Object, System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Int32 CompareTo(ReferenceOnDisk) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Int32 CompareTo(System.Object) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Int32 CompareTo(System.Object, System.Collections.IComparer) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Int32 GetHashCode() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Int32 GetHashCode(System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: System.DateTime LastModified +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: System.DateTime get_LastModified() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: System.String Path +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: System.String ToString() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: System.String get_Path() +FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk: Void .ctor(System.String, System.DateTime) +FSharp.Compiler.CodeAnalysis.ProjectSnapshot: FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpFileSnapshot +FSharp.Compiler.CodeAnalysis.ProjectSnapshot: FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectIdentifier +FSharp.Compiler.CodeAnalysis.ProjectSnapshot: FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot +FSharp.Compiler.CodeAnalysis.ProjectSnapshot: FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpReferencedProjectSnapshot +FSharp.Compiler.CodeAnalysis.ProjectSnapshot: FSharp.Compiler.CodeAnalysis.ProjectSnapshot+ReferenceOnDisk FSharp.Compiler.CompilerEnvironment: Boolean IsCheckerSupportedSubcategory(System.String) FSharp.Compiler.CompilerEnvironment: Boolean IsCompilable(System.String) FSharp.Compiler.CompilerEnvironment: Boolean IsScriptFile(System.String) @@ -4271,8 +4345,6 @@ FSharp.Compiler.EditorServices.ToolTipElementData: Void .ctor(Microsoft.FSharp.C FSharp.Compiler.EditorServices.ToolTipText: Boolean Equals(FSharp.Compiler.EditorServices.ToolTipText) FSharp.Compiler.EditorServices.ToolTipText: Boolean Equals(System.Object) FSharp.Compiler.EditorServices.ToolTipText: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.EditorServices.ToolTipText: Boolean IsToolTipText -FSharp.Compiler.EditorServices.ToolTipText: Boolean get_IsToolTipText() FSharp.Compiler.EditorServices.ToolTipText: FSharp.Compiler.EditorServices.ToolTipText NewToolTipText(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.EditorServices.ToolTipElement]) FSharp.Compiler.EditorServices.ToolTipText: Int32 GetHashCode() FSharp.Compiler.EditorServices.ToolTipText: Int32 GetHashCode(System.Collections.IEqualityComparer) @@ -4292,7 +4364,6 @@ FSharp.Compiler.EditorServices.TupledArgumentLocation: Int32 GetHashCode() FSharp.Compiler.EditorServices.TupledArgumentLocation: Int32 GetHashCode(System.Collections.IEqualityComparer) FSharp.Compiler.EditorServices.TupledArgumentLocation: System.String ToString() FSharp.Compiler.EditorServices.TupledArgumentLocation: Void .ctor(Boolean, FSharp.Compiler.Text.Range) -FSharp.Compiler.EditorServices.UnnecessaryParentheses: Microsoft.FSharp.Control.FSharpAsync`1[System.Collections.Generic.IEnumerable`1[FSharp.Compiler.Text.Range]] getUnnecessaryParentheses(Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.String], FSharp.Compiler.Syntax.ParsedInput) FSharp.Compiler.EditorServices.UnresolvedSymbol: Boolean Equals(FSharp.Compiler.EditorServices.UnresolvedSymbol) FSharp.Compiler.EditorServices.UnresolvedSymbol: Boolean Equals(System.Object) FSharp.Compiler.EditorServices.UnresolvedSymbol: Boolean Equals(System.Object, System.Collections.IEqualityComparer) @@ -4316,8 +4387,6 @@ FSharp.Compiler.EditorServices.XmlDocParser: Microsoft.FSharp.Collections.FSharp FSharp.Compiler.EditorServices.XmlDocable: Boolean Equals(FSharp.Compiler.EditorServices.XmlDocable) FSharp.Compiler.EditorServices.XmlDocable: Boolean Equals(System.Object) FSharp.Compiler.EditorServices.XmlDocable: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.EditorServices.XmlDocable: Boolean IsXmlDocable -FSharp.Compiler.EditorServices.XmlDocable: Boolean get_IsXmlDocable() FSharp.Compiler.EditorServices.XmlDocable: FSharp.Compiler.EditorServices.XmlDocable NewXmlDocable(Int32, Int32, Microsoft.FSharp.Collections.FSharpList`1[System.String]) FSharp.Compiler.EditorServices.XmlDocable: Int32 CompareTo(FSharp.Compiler.EditorServices.XmlDocable) FSharp.Compiler.EditorServices.XmlDocable: Int32 CompareTo(System.Object) @@ -5556,8 +5625,6 @@ FSharp.Compiler.Syntax.DebugPointAtInOrTo: System.String ToString() FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean Equals(FSharp.Compiler.Syntax.DebugPointAtLeafExpr) FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean Equals(System.Object) FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean IsYes -FSharp.Compiler.Syntax.DebugPointAtLeafExpr: Boolean get_IsYes() FSharp.Compiler.Syntax.DebugPointAtLeafExpr: FSharp.Compiler.Syntax.DebugPointAtLeafExpr NewYes(FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.DebugPointAtLeafExpr: FSharp.Compiler.Text.Range Item FSharp.Compiler.Syntax.DebugPointAtLeafExpr: FSharp.Compiler.Text.Range get_Item() @@ -5692,8 +5759,6 @@ FSharp.Compiler.Syntax.Ident: System.String ToString() FSharp.Compiler.Syntax.Ident: System.String get_idText() FSharp.Compiler.Syntax.Ident: System.String idText FSharp.Compiler.Syntax.Ident: Void .ctor(System.String, FSharp.Compiler.Text.Range) -FSharp.Compiler.Syntax.ParsedHashDirective: Boolean IsParsedHashDirective -FSharp.Compiler.Syntax.ParsedHashDirective: Boolean get_IsParsedHashDirective() FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Syntax.ParsedHashDirective NewParsedHashDirective(System.String, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirectiveArgument], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Text.Range range @@ -5732,8 +5797,6 @@ FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: FSharp.Compiler.Text.Range g FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: Int32 Tag FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: Int32 get_Tag() FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: System.String ToString() -FSharp.Compiler.Syntax.ParsedImplFile: Boolean IsParsedImplFile -FSharp.Compiler.Syntax.ParsedImplFile: Boolean get_IsParsedImplFile() FSharp.Compiler.Syntax.ParsedImplFile: FSharp.Compiler.Syntax.ParsedImplFile NewParsedImplFile(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirective], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedImplFileFragment]) FSharp.Compiler.Syntax.ParsedImplFile: Int32 Tag FSharp.Compiler.Syntax.ParsedImplFile: Int32 get_Tag() @@ -5785,11 +5848,9 @@ FSharp.Compiler.Syntax.ParsedImplFileFragment: Int32 get_Tag() FSharp.Compiler.Syntax.ParsedImplFileFragment: System.String ToString() FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsExe FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsLastCompiland -FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsParsedImplFileInput FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean IsScript FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsExe() FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsLastCompiland() -FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsParsedImplFileInput() FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_IsScript() FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean get_isScript() FSharp.Compiler.Syntax.ParsedImplFileInput: Boolean isScript @@ -5853,8 +5914,12 @@ FSharp.Compiler.Syntax.ParsedInput: Microsoft.FSharp.Collections.FSharpSet`1[Sys FSharp.Compiler.Syntax.ParsedInput: System.String FileName FSharp.Compiler.Syntax.ParsedInput: System.String ToString() FSharp.Compiler.Syntax.ParsedInput: System.String get_FileName() -FSharp.Compiler.Syntax.ParsedScriptInteraction: Boolean IsDefinitions -FSharp.Compiler.Syntax.ParsedScriptInteraction: Boolean get_IsDefinitions() +FSharp.Compiler.Syntax.ParsedInputModule: Boolean exists(Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode],Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SyntaxNode,System.Boolean]], FSharp.Compiler.Text.Position, FSharp.Compiler.Syntax.ParsedInput) +FSharp.Compiler.Syntax.ParsedInputModule: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Syntax.SyntaxNode,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode]]] tryNode(FSharp.Compiler.Text.Position, FSharp.Compiler.Syntax.ParsedInput) +FSharp.Compiler.Syntax.ParsedInputModule: Microsoft.FSharp.Core.FSharpOption`1[T] tryPickLast[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode],Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SyntaxNode,Microsoft.FSharp.Core.FSharpOption`1[T]]], FSharp.Compiler.Text.Position, FSharp.Compiler.Syntax.ParsedInput) +FSharp.Compiler.Syntax.ParsedInputModule: Microsoft.FSharp.Core.FSharpOption`1[T] tryPick[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode],Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SyntaxNode,Microsoft.FSharp.Core.FSharpOption`1[T]]], FSharp.Compiler.Text.Position, FSharp.Compiler.Syntax.ParsedInput) +FSharp.Compiler.Syntax.ParsedInputModule: State foldWhile[State](Microsoft.FSharp.Core.FSharpFunc`2[State,Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode],Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SyntaxNode,Microsoft.FSharp.Core.FSharpOption`1[State]]]], State, FSharp.Compiler.Syntax.ParsedInput) +FSharp.Compiler.Syntax.ParsedInputModule: State fold[State](Microsoft.FSharp.Core.FSharpFunc`2[State,Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode],Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SyntaxNode,State]]], State, FSharp.Compiler.Syntax.ParsedInput) FSharp.Compiler.Syntax.ParsedScriptInteraction: FSharp.Compiler.Syntax.ParsedScriptInteraction NewDefinitions(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.ParsedScriptInteraction: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.ParsedScriptInteraction: FSharp.Compiler.Text.Range range @@ -5863,8 +5928,6 @@ FSharp.Compiler.Syntax.ParsedScriptInteraction: Int32 get_Tag() FSharp.Compiler.Syntax.ParsedScriptInteraction: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl] defns FSharp.Compiler.Syntax.ParsedScriptInteraction: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl] get_defns() FSharp.Compiler.Syntax.ParsedScriptInteraction: System.String ToString() -FSharp.Compiler.Syntax.ParsedSigFile: Boolean IsParsedSigFile -FSharp.Compiler.Syntax.ParsedSigFile: Boolean get_IsParsedSigFile() FSharp.Compiler.Syntax.ParsedSigFile: FSharp.Compiler.Syntax.ParsedSigFile NewParsedSigFile(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirective], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedSigFileFragment]) FSharp.Compiler.Syntax.ParsedSigFile: Int32 Tag FSharp.Compiler.Syntax.ParsedSigFile: Int32 get_Tag() @@ -5914,8 +5977,6 @@ FSharp.Compiler.Syntax.ParsedSigFileFragment: FSharp.Compiler.Syntax.ParsedSigFi FSharp.Compiler.Syntax.ParsedSigFileFragment: Int32 Tag FSharp.Compiler.Syntax.ParsedSigFileFragment: Int32 get_Tag() FSharp.Compiler.Syntax.ParsedSigFileFragment: System.String ToString() -FSharp.Compiler.Syntax.ParsedSigFileInput: Boolean IsParsedSigFileInput -FSharp.Compiler.Syntax.ParsedSigFileInput: Boolean get_IsParsedSigFileInput() FSharp.Compiler.Syntax.ParsedSigFileInput: FSharp.Compiler.Syntax.ParsedSigFileInput NewParsedSigFileInput(System.String, FSharp.Compiler.Syntax.QualifiedNameOfFile, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ScopedPragma], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirective], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleOrNamespaceSig], FSharp.Compiler.SyntaxTrivia.ParsedSigFileInputTrivia, Microsoft.FSharp.Collections.FSharpSet`1[System.String]) FSharp.Compiler.Syntax.ParsedSigFileInput: FSharp.Compiler.Syntax.QualifiedNameOfFile QualifiedName FSharp.Compiler.Syntax.ParsedSigFileInput: FSharp.Compiler.Syntax.QualifiedNameOfFile get_QualifiedName() @@ -5988,8 +6049,6 @@ FSharp.Compiler.Syntax.PrettyNaming: System.String FormatAndOtherOverloadsString FSharp.Compiler.Syntax.PrettyNaming: System.String FsiDynamicModulePrefix FSharp.Compiler.Syntax.PrettyNaming: System.String NormalizeIdentifierBackticks(System.String) FSharp.Compiler.Syntax.PrettyNaming: System.String get_FsiDynamicModulePrefix() -FSharp.Compiler.Syntax.QualifiedNameOfFile: Boolean IsQualifiedNameOfFile -FSharp.Compiler.Syntax.QualifiedNameOfFile: Boolean get_IsQualifiedNameOfFile() FSharp.Compiler.Syntax.QualifiedNameOfFile: FSharp.Compiler.Syntax.Ident Id FSharp.Compiler.Syntax.QualifiedNameOfFile: FSharp.Compiler.Syntax.Ident Item FSharp.Compiler.Syntax.QualifiedNameOfFile: FSharp.Compiler.Syntax.Ident get_Id() @@ -6005,8 +6064,6 @@ FSharp.Compiler.Syntax.QualifiedNameOfFile: System.String get_Text() FSharp.Compiler.Syntax.ScopedPragma: Boolean Equals(FSharp.Compiler.Syntax.ScopedPragma) FSharp.Compiler.Syntax.ScopedPragma: Boolean Equals(System.Object) FSharp.Compiler.Syntax.ScopedPragma: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.Syntax.ScopedPragma: Boolean IsWarningOff -FSharp.Compiler.Syntax.ScopedPragma: Boolean get_IsWarningOff() FSharp.Compiler.Syntax.ScopedPragma: FSharp.Compiler.Syntax.ScopedPragma NewWarningOff(FSharp.Compiler.Text.Range, Int32) FSharp.Compiler.Syntax.ScopedPragma: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.ScopedPragma: FSharp.Compiler.Text.Range range @@ -6020,9 +6077,7 @@ FSharp.Compiler.Syntax.ScopedPragma: System.String ToString() FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(FSharp.Compiler.Syntax.SeqExprOnly) FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(System.Object) FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.Syntax.SeqExprOnly: Boolean IsSeqExprOnly FSharp.Compiler.Syntax.SeqExprOnly: Boolean Item -FSharp.Compiler.Syntax.SeqExprOnly: Boolean get_IsSeqExprOnly() FSharp.Compiler.Syntax.SeqExprOnly: Boolean get_Item() FSharp.Compiler.Syntax.SeqExprOnly: FSharp.Compiler.Syntax.SeqExprOnly NewSeqExprOnly(Boolean) FSharp.Compiler.Syntax.SeqExprOnly: Int32 CompareTo(FSharp.Compiler.Syntax.SeqExprOnly) @@ -6065,8 +6120,6 @@ FSharp.Compiler.Syntax.SynAccess: Int32 GetHashCode(System.Collections.IEquality FSharp.Compiler.Syntax.SynAccess: Int32 Tag FSharp.Compiler.Syntax.SynAccess: Int32 get_Tag() FSharp.Compiler.Syntax.SynAccess: System.String ToString() -FSharp.Compiler.Syntax.SynArgInfo: Boolean IsSynArgInfo -FSharp.Compiler.Syntax.SynArgInfo: Boolean get_IsSynArgInfo() FSharp.Compiler.Syntax.SynArgInfo: Boolean get_optional() FSharp.Compiler.Syntax.SynArgInfo: Boolean optional FSharp.Compiler.Syntax.SynArgInfo: FSharp.Compiler.Syntax.SynArgInfo NewSynArgInfo(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]) @@ -6123,8 +6176,6 @@ FSharp.Compiler.Syntax.SynAttributeList: Microsoft.FSharp.Collections.FSharpList FSharp.Compiler.Syntax.SynAttributeList: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttribute] get_Attributes() FSharp.Compiler.Syntax.SynAttributeList: System.String ToString() FSharp.Compiler.Syntax.SynAttributeList: Void .ctor(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttribute], FSharp.Compiler.Text.Range) -FSharp.Compiler.Syntax.SynBinding: Boolean IsSynBinding -FSharp.Compiler.Syntax.SynBinding: Boolean get_IsSynBinding() FSharp.Compiler.Syntax.SynBinding: Boolean get_isInline() FSharp.Compiler.Syntax.SynBinding: Boolean get_isMutable() FSharp.Compiler.Syntax.SynBinding: Boolean isInline @@ -6188,8 +6239,6 @@ FSharp.Compiler.Syntax.SynBindingKind: Int32 GetHashCode(System.Collections.IEqu FSharp.Compiler.Syntax.SynBindingKind: Int32 Tag FSharp.Compiler.Syntax.SynBindingKind: Int32 get_Tag() FSharp.Compiler.Syntax.SynBindingKind: System.String ToString() -FSharp.Compiler.Syntax.SynBindingReturnInfo: Boolean IsSynBindingReturnInfo -FSharp.Compiler.Syntax.SynBindingReturnInfo: Boolean get_IsSynBindingReturnInfo() FSharp.Compiler.Syntax.SynBindingReturnInfo: FSharp.Compiler.Syntax.SynBindingReturnInfo NewSynBindingReturnInfo(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.SyntaxTrivia.SynBindingReturnInfoTrivia) FSharp.Compiler.Syntax.SynBindingReturnInfo: FSharp.Compiler.Syntax.SynType get_typeName() FSharp.Compiler.Syntax.SynBindingReturnInfo: FSharp.Compiler.Syntax.SynType typeName @@ -6224,8 +6273,6 @@ FSharp.Compiler.Syntax.SynByteStringKind: Int32 GetHashCode(System.Collections.I FSharp.Compiler.Syntax.SynByteStringKind: Int32 Tag FSharp.Compiler.Syntax.SynByteStringKind: Int32 get_Tag() FSharp.Compiler.Syntax.SynByteStringKind: System.String ToString() -FSharp.Compiler.Syntax.SynComponentInfo: Boolean IsSynComponentInfo -FSharp.Compiler.Syntax.SynComponentInfo: Boolean get_IsSynComponentInfo() FSharp.Compiler.Syntax.SynComponentInfo: Boolean get_preferPostfix() FSharp.Compiler.Syntax.SynComponentInfo: Boolean preferPostfix FSharp.Compiler.Syntax.SynComponentInfo: FSharp.Compiler.Syntax.SynComponentInfo NewSynComponentInfo(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynTyparDecls], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynTypeConstraint], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Xml.PreXmlDoc, Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range) @@ -6425,8 +6472,6 @@ FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Text.Range Range(FSharp.Compile FSharp.Compiler.Syntax.SynConst: Int32 Tag FSharp.Compiler.Syntax.SynConst: Int32 get_Tag() FSharp.Compiler.Syntax.SynConst: System.String ToString() -FSharp.Compiler.Syntax.SynEnumCase: Boolean IsSynEnumCase -FSharp.Compiler.Syntax.SynEnumCase: Boolean get_IsSynEnumCase() FSharp.Compiler.Syntax.SynEnumCase: FSharp.Compiler.Syntax.SynEnumCase NewSynEnumCase(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynIdent, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynEnumCaseTrivia) FSharp.Compiler.Syntax.SynEnumCase: FSharp.Compiler.Syntax.SynExpr get_valueExpr() FSharp.Compiler.Syntax.SynEnumCase: FSharp.Compiler.Syntax.SynExpr valueExpr @@ -6445,8 +6490,6 @@ 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.SynExceptionDefn: Boolean IsSynExceptionDefn -FSharp.Compiler.Syntax.SynExceptionDefn: Boolean get_IsSynExceptionDefn() 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 FSharp.Compiler.Syntax.SynExceptionDefn: FSharp.Compiler.Syntax.SynExceptionDefnRepr get_exnRepr() @@ -6461,8 +6504,6 @@ FSharp.Compiler.Syntax.SynExceptionDefn: Microsoft.FSharp.Collections.FSharpList FSharp.Compiler.Syntax.SynExceptionDefn: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_withKeyword() FSharp.Compiler.Syntax.SynExceptionDefn: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] withKeyword FSharp.Compiler.Syntax.SynExceptionDefn: System.String ToString() -FSharp.Compiler.Syntax.SynExceptionDefnRepr: Boolean IsSynExceptionDefnRepr -FSharp.Compiler.Syntax.SynExceptionDefnRepr: Boolean get_IsSynExceptionDefnRepr() FSharp.Compiler.Syntax.SynExceptionDefnRepr: FSharp.Compiler.Syntax.SynExceptionDefnRepr NewSynExceptionDefnRepr(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynUnionCase, Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident]], FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExceptionDefnRepr: FSharp.Compiler.Syntax.SynUnionCase caseName FSharp.Compiler.Syntax.SynExceptionDefnRepr: FSharp.Compiler.Syntax.SynUnionCase get_caseName() @@ -6481,8 +6522,6 @@ FSharp.Compiler.Syntax.SynExceptionDefnRepr: Microsoft.FSharp.Core.FSharpOption` FSharp.Compiler.Syntax.SynExceptionDefnRepr: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident]] get_longId() FSharp.Compiler.Syntax.SynExceptionDefnRepr: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident]] longId FSharp.Compiler.Syntax.SynExceptionDefnRepr: System.String ToString() -FSharp.Compiler.Syntax.SynExceptionSig: Boolean IsSynExceptionSig -FSharp.Compiler.Syntax.SynExceptionSig: Boolean get_IsSynExceptionSig() FSharp.Compiler.Syntax.SynExceptionSig: FSharp.Compiler.Syntax.SynExceptionDefnRepr exnRepr FSharp.Compiler.Syntax.SynExceptionSig: FSharp.Compiler.Syntax.SynExceptionDefnRepr get_exnRepr() FSharp.Compiler.Syntax.SynExceptionSig: FSharp.Compiler.Syntax.SynExceptionSig NewSynExceptionSig(FSharp.Compiler.Syntax.SynExceptionDefnRepr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberSig], FSharp.Compiler.Text.Range) @@ -7417,8 +7456,6 @@ FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Text.Range get_RangeWithoutAnyEx FSharp.Compiler.Syntax.SynExpr: Int32 Tag FSharp.Compiler.Syntax.SynExpr: Int32 get_Tag() FSharp.Compiler.Syntax.SynExpr: System.String ToString() -FSharp.Compiler.Syntax.SynExprAndBang: Boolean IsSynExprAndBang -FSharp.Compiler.Syntax.SynExprAndBang: Boolean get_IsSynExprAndBang() FSharp.Compiler.Syntax.SynExprAndBang: Boolean get_isFromSource() FSharp.Compiler.Syntax.SynExprAndBang: Boolean get_isUse() FSharp.Compiler.Syntax.SynExprAndBang: Boolean isFromSource @@ -7437,8 +7474,7 @@ FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynExprAndBang: Int32 Tag FSharp.Compiler.Syntax.SynExprAndBang: Int32 get_Tag() FSharp.Compiler.Syntax.SynExprAndBang: System.String ToString() -FSharp.Compiler.Syntax.SynExprRecordField: Boolean IsSynExprRecordField -FSharp.Compiler.Syntax.SynExprRecordField: Boolean get_IsSynExprRecordField() +FSharp.Compiler.Syntax.SynExprModule: Boolean shouldBeParenthesizedInContext(Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynExpr) FSharp.Compiler.Syntax.SynExprRecordField: FSharp.Compiler.Syntax.SynExprRecordField NewSynExprRecordField(System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr], Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]) FSharp.Compiler.Syntax.SynExprRecordField: Int32 Tag FSharp.Compiler.Syntax.SynExprRecordField: Int32 get_Tag() @@ -7451,8 +7487,6 @@ FSharp.Compiler.Syntax.SynExprRecordField: Microsoft.FSharp.Core.FSharpOption`1[ FSharp.Compiler.Syntax.SynExprRecordField: System.String ToString() FSharp.Compiler.Syntax.SynExprRecordField: System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean] fieldName FSharp.Compiler.Syntax.SynExprRecordField: System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean] get_fieldName() -FSharp.Compiler.Syntax.SynField: Boolean IsSynField -FSharp.Compiler.Syntax.SynField: Boolean get_IsSynField() FSharp.Compiler.Syntax.SynField: Boolean get_isMutable() FSharp.Compiler.Syntax.SynField: Boolean get_isStatic() FSharp.Compiler.Syntax.SynField: Boolean isMutable @@ -7477,8 +7511,6 @@ FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Com FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] accessibility FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] get_accessibility() FSharp.Compiler.Syntax.SynField: System.String ToString() -FSharp.Compiler.Syntax.SynIdent: Boolean IsSynIdent -FSharp.Compiler.Syntax.SynIdent: Boolean get_IsSynIdent() FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.Ident get_ident() FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.Ident ident FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.SynIdent NewSynIdent(FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia]) @@ -7487,8 +7519,6 @@ FSharp.Compiler.Syntax.SynIdent: Int32 get_Tag() FSharp.Compiler.Syntax.SynIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia] get_trivia() FSharp.Compiler.Syntax.SynIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia] trivia FSharp.Compiler.Syntax.SynIdent: System.String ToString() -FSharp.Compiler.Syntax.SynInterfaceImpl: Boolean IsSynInterfaceImpl -FSharp.Compiler.Syntax.SynInterfaceImpl: Boolean get_IsSynInterfaceImpl() FSharp.Compiler.Syntax.SynInterfaceImpl: FSharp.Compiler.Syntax.SynInterfaceImpl NewSynInterfaceImpl(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynBinding], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynInterfaceImpl: FSharp.Compiler.Syntax.SynType get_interfaceTy() FSharp.Compiler.Syntax.SynInterfaceImpl: FSharp.Compiler.Syntax.SynType interfaceTy @@ -7525,9 +7555,7 @@ FSharp.Compiler.Syntax.SynInterpolatedStringPart: FSharp.Compiler.Syntax.SynInte FSharp.Compiler.Syntax.SynInterpolatedStringPart: Int32 Tag FSharp.Compiler.Syntax.SynInterpolatedStringPart: Int32 get_Tag() FSharp.Compiler.Syntax.SynInterpolatedStringPart: System.String ToString() -FSharp.Compiler.Syntax.SynLongIdent: Boolean IsSynLongIdent FSharp.Compiler.Syntax.SynLongIdent: Boolean ThereIsAnExtraDotAtTheEnd -FSharp.Compiler.Syntax.SynLongIdent: Boolean get_IsSynLongIdent() FSharp.Compiler.Syntax.SynLongIdent: Boolean get_ThereIsAnExtraDotAtTheEnd() FSharp.Compiler.Syntax.SynLongIdent: FSharp.Compiler.Syntax.SynLongIdent NewSynLongIdent(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia]]) FSharp.Compiler.Syntax.SynLongIdent: FSharp.Compiler.Text.Range Range @@ -7553,8 +7581,6 @@ FSharp.Compiler.Syntax.SynLongIdent: Microsoft.FSharp.Collections.FSharpList`1[M FSharp.Compiler.Syntax.SynLongIdent: System.String ToString() FSharp.Compiler.Syntax.SynLongIdentHelpers: FSharp.Compiler.Syntax.SynLongIdent LongIdentWithDots(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range]) FSharp.Compiler.Syntax.SynLongIdentHelpers: System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident],Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range]] |LongIdentWithDots|(FSharp.Compiler.Syntax.SynLongIdent) -FSharp.Compiler.Syntax.SynMatchClause: Boolean IsSynMatchClause -FSharp.Compiler.Syntax.SynMatchClause: Boolean get_IsSynMatchClause() FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.DebugPointAtTarget debugPoint FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.DebugPointAtTarget get_debugPoint() FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.SynExpr get_resultExpr() @@ -7708,8 +7734,8 @@ FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: Microsoft.FSharp.Core.FSharpO FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding] get_memberDefnForSet() FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding] memberDefnForGet FSharp.Compiler.Syntax.SynMemberDefn+GetSetMember: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding] memberDefnForSet -FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.Syntax.SynSimplePats ctorArgs -FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.Syntax.SynSimplePats get_ctorArgs() +FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.Syntax.SynPat ctorArgs +FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.Syntax.SynPat get_ctorArgs() FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.SyntaxTrivia.SynMemberDefnImplicitCtorTrivia get_trivia() FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.SyntaxTrivia.SynMemberDefnImplicitCtorTrivia trivia FSharp.Compiler.Syntax.SynMemberDefn+ImplicitCtor: FSharp.Compiler.Text.Range get_range() @@ -7809,7 +7835,7 @@ FSharp.Compiler.Syntax.SynMemberDefn: Boolean get_IsValField() FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewAbstractSlot(FSharp.Compiler.Syntax.SynValSig, FSharp.Compiler.Syntax.SynMemberFlags, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnAbstractSlotTrivia) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewAutoProperty(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Boolean, FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynType], FSharp.Compiler.Syntax.SynMemberKind, FSharp.Compiler.Syntax.SynMemberFlags, FSharp.Compiler.Syntax.SynMemberFlags, FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnAutoPropertyTrivia) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewGetSetMember(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia) -FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitCtor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynSimplePats, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnImplicitCtorTrivia) +FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitCtor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynPat, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnImplicitCtorTrivia) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitInherit(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewInherit(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewInterface(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn]], FSharp.Compiler.Text.Range) @@ -8052,8 +8078,6 @@ FSharp.Compiler.Syntax.SynModuleDecl: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynModuleDecl: Int32 Tag FSharp.Compiler.Syntax.SynModuleDecl: Int32 get_Tag() FSharp.Compiler.Syntax.SynModuleDecl: System.String ToString() -FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean IsSynModuleOrNamespace -FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean get_IsSynModuleOrNamespace() FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean get_isRecursive() FSharp.Compiler.Syntax.SynModuleOrNamespace: Boolean isRecursive FSharp.Compiler.Syntax.SynModuleOrNamespace: FSharp.Compiler.Syntax.SynModuleOrNamespace NewSynModuleOrNamespace(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.Ident], Boolean, FSharp.Compiler.Syntax.SynModuleOrNamespaceKind, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynModuleDecl], FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynModuleOrNamespaceTrivia) @@ -8112,8 +8136,6 @@ FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: Int32 GetHashCode(System.Collec FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: Int32 Tag FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: Int32 get_Tag() FSharp.Compiler.Syntax.SynModuleOrNamespaceKind: System.String ToString() -FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean IsSynModuleOrNamespaceSig -FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean get_IsSynModuleOrNamespaceSig() FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean get_isRecursive() FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: Boolean isRecursive FSharp.Compiler.Syntax.SynModuleOrNamespaceSig: FSharp.Compiler.Syntax.SynModuleOrNamespaceKind get_kind() @@ -8466,6 +8488,7 @@ FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynPat: Int32 Tag FSharp.Compiler.Syntax.SynPat: Int32 get_Tag() FSharp.Compiler.Syntax.SynPat: System.String ToString() +FSharp.Compiler.Syntax.SynPatModule: Boolean shouldBeParenthesizedInContext(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynPat) FSharp.Compiler.Syntax.SynRationalConst+Integer: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynRationalConst+Integer: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynRationalConst+Integer: Int32 get_value() @@ -8514,8 +8537,6 @@ FSharp.Compiler.Syntax.SynRationalConst: FSharp.Compiler.Syntax.SynRationalConst FSharp.Compiler.Syntax.SynRationalConst: Int32 Tag FSharp.Compiler.Syntax.SynRationalConst: Int32 get_Tag() FSharp.Compiler.Syntax.SynRationalConst: System.String ToString() -FSharp.Compiler.Syntax.SynReturnInfo: Boolean IsSynReturnInfo -FSharp.Compiler.Syntax.SynReturnInfo: Boolean get_IsSynReturnInfo() FSharp.Compiler.Syntax.SynReturnInfo: FSharp.Compiler.Syntax.SynReturnInfo NewSynReturnInfo(System.Tuple`2[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Syntax.SynArgInfo], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynReturnInfo: FSharp.Compiler.Text.Range Range FSharp.Compiler.Syntax.SynReturnInfo: FSharp.Compiler.Text.Range get_Range() @@ -8589,8 +8610,6 @@ FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: FSharp.Compiler.Syntax.Syn FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: Int32 Tag FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: Int32 get_Tag() FSharp.Compiler.Syntax.SynSimplePatAlternativeIdInfo: System.String ToString() -FSharp.Compiler.Syntax.SynSimplePats: Boolean IsSimplePats -FSharp.Compiler.Syntax.SynSimplePats: Boolean get_IsSimplePats() FSharp.Compiler.Syntax.SynSimplePats: FSharp.Compiler.Syntax.SynSimplePats NewSimplePats(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynSimplePat], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynSimplePats: FSharp.Compiler.Text.Range Range FSharp.Compiler.Syntax.SynSimplePats: FSharp.Compiler.Text.Range get_Range() @@ -8681,8 +8700,6 @@ FSharp.Compiler.Syntax.SynTupleTypeSegment: FSharp.Compiler.Text.Range get_Range FSharp.Compiler.Syntax.SynTupleTypeSegment: Int32 Tag FSharp.Compiler.Syntax.SynTupleTypeSegment: Int32 get_Tag() FSharp.Compiler.Syntax.SynTupleTypeSegment: System.String ToString() -FSharp.Compiler.Syntax.SynTypar: Boolean IsSynTypar -FSharp.Compiler.Syntax.SynTypar: Boolean get_IsSynTypar() FSharp.Compiler.Syntax.SynTypar: Boolean get_isCompGen() FSharp.Compiler.Syntax.SynTypar: Boolean isCompGen FSharp.Compiler.Syntax.SynTypar: FSharp.Compiler.Syntax.Ident get_ident() @@ -8695,8 +8712,6 @@ FSharp.Compiler.Syntax.SynTypar: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynTypar: Int32 Tag FSharp.Compiler.Syntax.SynTypar: Int32 get_Tag() FSharp.Compiler.Syntax.SynTypar: System.String ToString() -FSharp.Compiler.Syntax.SynTyparDecl: Boolean IsSynTyparDecl -FSharp.Compiler.Syntax.SynTyparDecl: Boolean get_IsSynTyparDecl() FSharp.Compiler.Syntax.SynTyparDecl: FSharp.Compiler.Syntax.SynTypar get_typar() FSharp.Compiler.Syntax.SynTyparDecl: FSharp.Compiler.Syntax.SynTypar typar FSharp.Compiler.Syntax.SynTyparDecl: FSharp.Compiler.Syntax.SynTyparDecl NewSynTyparDecl(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynTypar, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynType], FSharp.Compiler.SyntaxTrivia.SynTyparDeclTrivia) @@ -9129,8 +9144,6 @@ FSharp.Compiler.Syntax.SynTypeConstraint: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynTypeConstraint: Int32 Tag FSharp.Compiler.Syntax.SynTypeConstraint: Int32 get_Tag() FSharp.Compiler.Syntax.SynTypeConstraint: System.String ToString() -FSharp.Compiler.Syntax.SynTypeDefn: Boolean IsSynTypeDefn -FSharp.Compiler.Syntax.SynTypeDefn: Boolean get_IsSynTypeDefn() FSharp.Compiler.Syntax.SynTypeDefn: FSharp.Compiler.Syntax.SynComponentInfo get_typeInfo() FSharp.Compiler.Syntax.SynTypeDefn: FSharp.Compiler.Syntax.SynComponentInfo typeInfo FSharp.Compiler.Syntax.SynTypeDefn: FSharp.Compiler.Syntax.SynTypeDefn NewSynTypeDefn(FSharp.Compiler.Syntax.SynComponentInfo, FSharp.Compiler.Syntax.SynTypeDefnRepr, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberDefn], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynTypeDefnTrivia) @@ -9247,8 +9260,6 @@ FSharp.Compiler.Syntax.SynTypeDefnRepr: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynTypeDefnRepr: Int32 Tag FSharp.Compiler.Syntax.SynTypeDefnRepr: Int32 get_Tag() FSharp.Compiler.Syntax.SynTypeDefnRepr: System.String ToString() -FSharp.Compiler.Syntax.SynTypeDefnSig: Boolean IsSynTypeDefnSig -FSharp.Compiler.Syntax.SynTypeDefnSig: Boolean get_IsSynTypeDefnSig() FSharp.Compiler.Syntax.SynTypeDefnSig: FSharp.Compiler.Syntax.SynComponentInfo get_typeInfo() FSharp.Compiler.Syntax.SynTypeDefnSig: FSharp.Compiler.Syntax.SynComponentInfo typeInfo FSharp.Compiler.Syntax.SynTypeDefnSig: FSharp.Compiler.Syntax.SynTypeDefnSig NewSynTypeDefnSig(FSharp.Compiler.Syntax.SynComponentInfo, FSharp.Compiler.Syntax.SynTypeDefnSigRepr, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberSig], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynTypeDefnSigTrivia) @@ -9318,8 +9329,8 @@ FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Collectio FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.Syntax.SynValSig,FSharp.Compiler.Syntax.SynMemberFlags]] slotsigs FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]]] get_inherits() FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]]] inherits -FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynSimplePats] get_implicitCtorSynPats() -FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynSimplePats] implicitCtorSynPats +FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynPat] get_implicitCtorSynPats() +FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+General: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynPat] implicitCtorSynPats FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+LibraryOnlyILAssembly: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+LibraryOnlyILAssembly: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+LibraryOnlyILAssembly: System.Object get_ilType() @@ -9370,7 +9381,7 @@ FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: Boolean get_IsTypeAbbrev() FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: Boolean get_IsUnion() FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewEnum(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynEnumCase], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewException(FSharp.Compiler.Syntax.SynExceptionDefnRepr) -FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewGeneral(FSharp.Compiler.Syntax.SynTypeDefnKind, Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]]], Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.Syntax.SynValSig,FSharp.Compiler.Syntax.SynMemberFlags]], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynField], Boolean, Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynSimplePats], FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewGeneral(FSharp.Compiler.Syntax.SynTypeDefnKind, Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]]], Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.Syntax.SynValSig,FSharp.Compiler.Syntax.SynMemberFlags]], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynField], Boolean, Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynPat], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewLibraryOnlyILAssembly(System.Object, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewNone(FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewRecord(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynField], FSharp.Compiler.Text.Range) @@ -9390,8 +9401,6 @@ FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Text.Range get_Ran FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: Int32 Tag FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: Int32 get_Tag() FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: System.String ToString() -FSharp.Compiler.Syntax.SynUnionCase: Boolean IsSynUnionCase -FSharp.Compiler.Syntax.SynUnionCase: Boolean get_IsSynUnionCase() FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynIdent get_ident() FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynIdent ident FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynUnionCase NewSynUnionCase(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynIdent, FSharp.Compiler.Syntax.SynUnionCaseKind, FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynUnionCaseTrivia) @@ -9432,8 +9441,6 @@ FSharp.Compiler.Syntax.SynUnionCaseKind: FSharp.Compiler.Syntax.SynUnionCaseKind FSharp.Compiler.Syntax.SynUnionCaseKind: Int32 Tag FSharp.Compiler.Syntax.SynUnionCaseKind: Int32 get_Tag() FSharp.Compiler.Syntax.SynUnionCaseKind: System.String ToString() -FSharp.Compiler.Syntax.SynValData: Boolean IsSynValData -FSharp.Compiler.Syntax.SynValData: Boolean get_IsSynValData() FSharp.Compiler.Syntax.SynValData: FSharp.Compiler.Syntax.SynValData NewSynValData(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberFlags], FSharp.Compiler.Syntax.SynValInfo, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]) FSharp.Compiler.Syntax.SynValData: FSharp.Compiler.Syntax.SynValInfo SynValInfo FSharp.Compiler.Syntax.SynValData: FSharp.Compiler.Syntax.SynValInfo get_SynValInfo() @@ -9446,8 +9453,6 @@ FSharp.Compiler.Syntax.SynValData: Microsoft.FSharp.Core.FSharpOption`1[FSharp.C FSharp.Compiler.Syntax.SynValData: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberFlags] get_memberFlags() FSharp.Compiler.Syntax.SynValData: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynMemberFlags] memberFlags FSharp.Compiler.Syntax.SynValData: System.String ToString() -FSharp.Compiler.Syntax.SynValInfo: Boolean IsSynValInfo -FSharp.Compiler.Syntax.SynValInfo: Boolean get_IsSynValInfo() FSharp.Compiler.Syntax.SynValInfo: FSharp.Compiler.Syntax.SynArgInfo get_returnInfo() FSharp.Compiler.Syntax.SynValInfo: FSharp.Compiler.Syntax.SynArgInfo returnInfo FSharp.Compiler.Syntax.SynValInfo: FSharp.Compiler.Syntax.SynValInfo NewSynValInfo(Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynArgInfo]], FSharp.Compiler.Syntax.SynArgInfo) @@ -9460,8 +9465,6 @@ FSharp.Compiler.Syntax.SynValInfo: Microsoft.FSharp.Collections.FSharpList`1[Mic FSharp.Compiler.Syntax.SynValInfo: Microsoft.FSharp.Collections.FSharpList`1[System.String] ArgNames FSharp.Compiler.Syntax.SynValInfo: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_ArgNames() FSharp.Compiler.Syntax.SynValInfo: System.String ToString() -FSharp.Compiler.Syntax.SynValSig: Boolean IsSynValSig -FSharp.Compiler.Syntax.SynValSig: Boolean get_IsSynValSig() FSharp.Compiler.Syntax.SynValSig: Boolean get_isInline() FSharp.Compiler.Syntax.SynValSig: Boolean get_isMutable() FSharp.Compiler.Syntax.SynValSig: Boolean isInline @@ -9496,9 +9499,7 @@ FSharp.Compiler.Syntax.SynValSig: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Co FSharp.Compiler.Syntax.SynValSig: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr] get_synExpr() FSharp.Compiler.Syntax.SynValSig: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr] synExpr FSharp.Compiler.Syntax.SynValSig: System.String ToString() -FSharp.Compiler.Syntax.SynValTyparDecls: Boolean IsSynValTyparDecls FSharp.Compiler.Syntax.SynValTyparDecls: Boolean canInfer -FSharp.Compiler.Syntax.SynValTyparDecls: Boolean get_IsSynValTyparDecls() FSharp.Compiler.Syntax.SynValTyparDecls: Boolean get_canInfer() FSharp.Compiler.Syntax.SynValTyparDecls: FSharp.Compiler.Syntax.SynValTyparDecls NewSynValTyparDecls(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynTyparDecls], Boolean) FSharp.Compiler.Syntax.SynValTyparDecls: Int32 Tag @@ -9605,9 +9606,12 @@ FSharp.Compiler.Syntax.SyntaxNode: FSharp.Compiler.Syntax.SyntaxNode+SynTypeDefn FSharp.Compiler.Syntax.SyntaxNode: FSharp.Compiler.Syntax.SyntaxNode+SynTypeDefnSig FSharp.Compiler.Syntax.SyntaxNode: FSharp.Compiler.Syntax.SyntaxNode+SynValSig FSharp.Compiler.Syntax.SyntaxNode: FSharp.Compiler.Syntax.SyntaxNode+Tags +FSharp.Compiler.Syntax.SyntaxNode: FSharp.Compiler.Text.Range Range +FSharp.Compiler.Syntax.SyntaxNode: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SyntaxNode: Int32 Tag FSharp.Compiler.Syntax.SyntaxNode: Int32 get_Tag() FSharp.Compiler.Syntax.SyntaxNode: System.String ToString() +FSharp.Compiler.Syntax.SyntaxNodeModule: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList] |Attributes|(FSharp.Compiler.Syntax.SyntaxNode) FSharp.Compiler.Syntax.SyntaxTraversal: Microsoft.FSharp.Core.FSharpOption`1[T] Traverse[T](FSharp.Compiler.Text.Position, FSharp.Compiler.Syntax.ParsedInput, FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitAttributeApplication(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynAttributeList) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitBinding(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynBinding,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynBinding) @@ -9627,7 +9631,7 @@ FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOptio FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitPat(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynPat,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynPat) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitRecordDefn(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynField], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitRecordField(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynLongIdent]) -FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitSimplePats(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynSimplePat]) +FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitSimplePats(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynPat) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitType(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynType,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynType) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitTypeAbbrev(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitUnionDefn(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynUnionCase], FSharp.Compiler.Text.Range) @@ -10344,6 +10348,7 @@ FSharp.Compiler.Text.ISourceText: System.String GetSubTextFromRange(FSharp.Compi FSharp.Compiler.Text.ISourceText: System.String GetSubTextString(Int32, Int32) FSharp.Compiler.Text.ISourceText: System.Tuple`2[System.Int32,System.Int32] GetLastCharacterPosition() FSharp.Compiler.Text.ISourceText: Void CopyTo(Int32, Char[], Int32, Int32) +FSharp.Compiler.Text.ISourceTextNew: System.Collections.Immutable.ImmutableArray`1[System.Byte] GetChecksum() FSharp.Compiler.Text.Line: Int32 fromZ(Int32) FSharp.Compiler.Text.Line: Int32 toZ(Int32) FSharp.Compiler.Text.NavigableTaggedText: FSharp.Compiler.Text.Range Range @@ -10423,6 +10428,8 @@ FSharp.Compiler.Text.RangeModule: System.Tuple`2[System.String,System.Tuple`2[Sy FSharp.Compiler.Text.RangeModule: System.Tuple`2[System.Tuple`2[System.Int32,System.Int32],System.Tuple`2[System.Int32,System.Int32]] toZ(FSharp.Compiler.Text.Range) FSharp.Compiler.Text.RangeModule: Void outputRange(System.IO.TextWriter, FSharp.Compiler.Text.Range) FSharp.Compiler.Text.SourceText: FSharp.Compiler.Text.ISourceText ofString(System.String) +FSharp.Compiler.Text.SourceTextNew: FSharp.Compiler.Text.ISourceTextNew ofISourceText(FSharp.Compiler.Text.ISourceText) +FSharp.Compiler.Text.SourceTextNew: FSharp.Compiler.Text.ISourceTextNew ofString(System.String) FSharp.Compiler.Text.TaggedText: FSharp.Compiler.Text.TextTag Tag FSharp.Compiler.Text.TaggedText: FSharp.Compiler.Text.TextTag get_Tag() FSharp.Compiler.Text.TaggedText: System.String Text diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 9281c75120e..0c042c439ae 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -5,13 +5,6 @@ Exe net472;net8.0 net8.0 - - $(NoWarn);NU1505 $(NoWarn);44;75; true false @@ -99,7 +92,8 @@ - + + Program.fs diff --git a/tests/FSharp.Compiler.Service.Tests/SynExprTests.fs b/tests/FSharp.Compiler.Service.Tests/SynExprTests.fs new file mode 100644 index 00000000000..1e402a1d252 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/SynExprTests.fs @@ -0,0 +1,88 @@ +module FSharp.Compiler.Syntax.Tests.SynExpr + +open FSharp.Compiler.Service.Tests.Common +open FSharp.Compiler.Syntax +open FSharp.Compiler.Text +open NUnit.Framework + +type Parenthesization = Needed | Unneeded + +module Parenthesization = + let ofBool shouldParenthesize = + if shouldParenthesize then Needed + else Unneeded + +let exprs: obj array list = + [ + [|([] : Parenthesization list); "()"|] + [|[Needed]; "(1 + 2) * 3"|] + [|[Unneeded]; "1 + (2 * 3)"|] + [|[Unneeded]; "1 * (2 * 3)"|] + [|[Unneeded]; "(1 * 2) * 3"|] + [|[Needed]; "1 / (2 / 3)"|] + [|[Unneeded]; "(1 / 2) / 3"|] + [|[Unneeded]; "(printfn \"Hello, world.\")"|] + [|[Needed]; "let (~-) x = x in id -(<@ 3 @>)"|] + [|[Unneeded; Unneeded]; "let (~-) x = x in id (-(<@ 3 @>))"|] + [|[Unneeded]; "(())"|] + [|[Unneeded]; "(3)"|] + [|[Needed]; + " + let x = (x + + y) + in x + " + |] + [|[Unneeded]; + " + let x = (x + + y) + in x + " + |] + [|[Needed]; + " + async { + return ( + 1 + ) + } + " + |] + [|[Unneeded]; + " + async { + return ( + 1 + ) + } + " + |] + ] + +#if !NET6_0_OR_GREATER +open System + +type String with + // This is not a true polyfill, but it suffices for the .NET Framework target. + member this.ReplaceLineEndings() = this.Replace("\r", "") +#endif + +// `expected` represents whether each parenthesized expression, from the inside outward, requires its parentheses. +[] +let shouldBeParenthesizedInContext (expected: Parenthesization list) src = + let ast = getParseResults src + + let getSourceLineStr = + let lines = src.ReplaceLineEndings().Split '\n' + Line.toZ >> Array.get lines + + let actual = + ([], ast) + ||> ParsedInput.fold (fun actual path node -> + match node, path with + | SyntaxNode.SynExpr expr, SyntaxNode.SynExpr(SynExpr.Paren _) :: path -> + Parenthesization.ofBool (SynExpr.shouldBeParenthesizedInContext getSourceLineStr path expr) :: actual + | _ -> actual) + + CollectionAssert.AreEqual(expected, actual) diff --git a/tests/FSharp.Compiler.Service.Tests/SynPatTests.fs b/tests/FSharp.Compiler.Service.Tests/SynPatTests.fs new file mode 100644 index 00000000000..42a5e8711e0 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/SynPatTests.fs @@ -0,0 +1,36 @@ +module FSharp.Compiler.Syntax.Tests.SynPat + +open FSharp.Compiler.Service.Tests.Common +open FSharp.Compiler.Syntax +open NUnit.Framework + +type Parenthesization = Needed | Unneeded + +module Parenthesization = + let ofBool shouldParenthesize = + if shouldParenthesize then Needed + else Unneeded + +let pats: obj array list = + [ + [|[Needed]; "match () with () -> ()"|] + [|[Needed]; "let (Lazy x) = lazy 1"|] + [|[Unneeded; Unneeded]; "let ((Lazy x)) = lazy 1"|] + [|[Needed; Unneeded]; "let (()) = ()"|] + [|[Needed; Unneeded; Unneeded]; "let ((())) = ()"|] + ] + +// `expected` represents whether each parenthesized pattern, from the inside outward, requires its parentheses. +[] +let shouldBeParenthesizedInContext (expected: Parenthesization list) src = + let ast = getParseResults src + + let actual = + ([], ast) + ||> ParsedInput.fold (fun actual path node -> + match node, path with + | SyntaxNode.SynPat pat, SyntaxNode.SynPat(SynPat.Paren _) :: path -> + Parenthesization.ofBool (SynPat.shouldBeParenthesizedInContext path pat) :: actual + | _ -> actual) + + CollectionAssert.AreEqual(expected, actual) \ No newline at end of file diff --git a/tests/FSharp.Compiler.Service.Tests/UnnecessaryParenthesesTests.fs b/tests/FSharp.Compiler.Service.Tests/UnnecessaryParenthesesTests.fs deleted file mode 100644 index 4ccbe93e470..00000000000 --- a/tests/FSharp.Compiler.Service.Tests/UnnecessaryParenthesesTests.fs +++ /dev/null @@ -1,52 +0,0 @@ -module FSharp.Compiler.EditorServices.Tests.UnnecessaryParenthesesTests - -open FSharp.Compiler.EditorServices -open FSharp.Compiler.Service.Tests.Common -open NUnit.Framework - -let noUnneededParens = - [ - "printfn \"Hello, world.\"" - "()" - "(1 + 2) * 3" - "let (~-) x = x in id -(<@ 3 @>)" - ] - -[] -let ``No results returned when there are no unnecessary parentheses`` src = - task { - let ast = getParseResults src - let! unnecessaryParentheses = UnnecessaryParentheses.getUnnecessaryParentheses (fun _ -> src) ast - Assert.IsEmpty unnecessaryParentheses - } - -let unneededParens = - [ - "(printfn \"Hello, world.\")" - "(())" - "(1 * 2) * 3" - "let (~-) x = x in -(<@ 3 @>)" - ] - -[] -let ``Results returned when there are unnecessary parentheses`` src = - task { - let ast = getParseResults src - let! unnecessaryParentheses = UnnecessaryParentheses.getUnnecessaryParentheses (fun _ -> src) ast - Assert.AreEqual(1, Seq.length unnecessaryParentheses, $"Expected one range but got: %A{unnecessaryParentheses}.") - } - -let nestedUnneededParens = - [ - "((printfn \"Hello, world.\"))" - "((3))" - "let (~-) x = x in id (-(<@ 3 @>))" - ] - -[] -let ``Results returned for nested, potentially mutually-exclusive, unnecessary parentheses`` src = - task { - let ast = getParseResults src - let! unnecessaryParentheses = UnnecessaryParentheses.getUnnecessaryParentheses (fun _ -> src) ast - Assert.AreEqual(2, Seq.length unnecessaryParentheses, $"Expected two ranges but got: %A{unnecessaryParentheses}.") - } diff --git a/tests/FSharp.Compiler.UnitTests/FSharp.Compiler.UnitTests.fsproj b/tests/FSharp.Compiler.UnitTests/FSharp.Compiler.UnitTests.fsproj index 915332ac4ac..0e4b91b42a7 100644 --- a/tests/FSharp.Compiler.UnitTests/FSharp.Compiler.UnitTests.fsproj +++ b/tests/FSharp.Compiler.UnitTests/FSharp.Compiler.UnitTests.fsproj @@ -74,6 +74,7 @@ CompilerService\ServiceUntypedParseTests.fs + diff --git a/tests/FSharp.Compiler.UnitTests/ParsedInputModuleTests.fs b/tests/FSharp.Compiler.UnitTests/ParsedInputModuleTests.fs new file mode 100644 index 00000000000..635c000f4af --- /dev/null +++ b/tests/FSharp.Compiler.UnitTests/ParsedInputModuleTests.fs @@ -0,0 +1,449 @@ +module Tests.Service.ParsedInputModuleTests + +open FSharp.Compiler.Service.Tests.Common +open FSharp.Compiler.Syntax +open FSharp.Compiler.Text.Position +open Xunit + +[] +let ``tryPick type test`` () = + let source = "123 :? int" + let parseTree = parseSourceCode ("C:\\test.fs", source) + + (mkPos 1 11, parseTree) + ||> ParsedInput.tryPick (fun _path node -> match node with SyntaxNode.SynType _ -> Some() | _ -> None) + |> Option.defaultWith (fun _ -> failwith "Did not visit type") + + (mkPos 1 3, parseTree) + ||> ParsedInput.tryPick (fun _path node -> match node with SyntaxNode.SynType _ -> Some() | _ -> None) + |> Option.iter (fun _ -> failwith "Should not visit type") + +[] +let ``tryPick record definition test`` () = + let source = "type R = { A: int; B: string }" + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let fields = + (pos0, parseTree) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynTypeDefn(SynTypeDefn(typeRepr = SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.Record(recordFields = fields), _))) -> Some fields + | _ -> None) + + match fields with + | Some [ SynField (idOpt = Some id1); SynField (idOpt = Some id2) ] when id1.idText = "A" && id2.idText = "B" -> () + | _ -> failwith "Did not visit record definition" + +[] +let ``tryPick union definition test`` () = + let source = "type U = A | B of string" + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let cases = + (pos0, parseTree) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynTypeDefn(SynTypeDefn(typeRepr = SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.Union(unionCases = cases), _))) -> Some cases + | _ -> None) + + match cases with + | Some [ SynUnionCase (ident = SynIdent(id1,_)); SynUnionCase (ident = SynIdent(id2,_)) ] when id1.idText = "A" && id2.idText = "B" -> () + | _ -> failwith "Did not visit union definition" + +[] +let ``tryPick enum definition test`` () = + let source = "type E = A = 0 | B = 1" + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let cases = + (pos0, parseTree) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynTypeDefn(SynTypeDefn(typeRepr = SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.Enum(cases = cases), _))) -> Some cases + | _ -> None) + + match cases with + | Some [ SynEnumCase (ident = SynIdent (id1, _)); SynEnumCase (ident = SynIdent (id2, _)) ] when id1.idText = "A" && id2.idText = "B" -> () + | _ -> failwith "Did not visit enum definition" + +[] +let ``tryPick recursive let binding`` () = + let source = "let rec fib n = if n < 2 then n else fib (n - 1) + fib (n - 2) in fib 10" + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let bindings = + (pos0, parseTree) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynExpr(SynExpr.LetOrUse(isRecursive = false)) -> failwith "isRecursive should be true" + | SyntaxNode.SynExpr(SynExpr.LetOrUse(isRecursive = true; bindings = bindings)) -> Some bindings + | _ -> None) + + match bindings with + | Some [ SynBinding(valData = SynValData(valInfo = SynValInfo(curriedArgInfos = [ [ SynArgInfo(ident = Some id) ] ]))) ] when id.idText = "n" -> () + | _ -> failwith "Did not visit recursive let binding" + +[] +let ``tryPick ValSig`` () = + let source = """ +module X + +val y: int -> int +""" + + let parseTree = parseSourceCode ("C:\\test.fsi", source) + + let ident = + (pos0, parseTree) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynValSig(SynValSig(ident = SynIdent(ident = ident))) -> Some ident.idText + | _ -> None) + + match ident with + | Some "y" -> () + | _ -> failwith "Did not visit SynValSig" + +[] +let ``tryPick nested ValSig`` () = + let source = """ +module X + +module Y = + val z: int -> int +""" + + let parseTree = parseSourceCode ("C:\\test.fsi", source) + + let ident = + (pos0, parseTree) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynValSig(SynValSig(ident = SynIdent(ident = ident))) -> Some ident.idText + | _ -> None) + + match ident with + | Some "z" -> () + | _ -> failwith "Did not visit SynValSig" + +[] +let ``tryPick Record in SynTypeDefnSig`` () = + let source = """ +module X + +type Y = + { + A: int + B: char + C: string + } +""" + + let parseTree = parseSourceCode ("C:\\test.fsi", source) + + let ident = + (pos0, parseTree) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynTypeDefnSig(SynTypeDefnSig(typeRepr = SynTypeDefnSigRepr.Simple(SynTypeDefnSimpleRepr.Record(recordFields = fields), _))) -> + fields + |> List.choose (function SynField(idOpt = Some ident) -> Some ident.idText | _ -> None) + |> String.concat "," + |> Some + | _ -> None) + + match ident with + | Some "A,B,C" -> () + | _ -> failwith "Did not visit SynTypeDefnSimpleRepr.Record in SynTypeDefnSig" + +[] +let ``tryPick SynValSig in SynMemberSig`` () = + let source = """ +module Lib + +type Meh = + new: unit -> Meh + member Foo: y: int -> int +""" + + let parseTree = parseSourceCode ("C:\\test.fsi", source) + let pos = mkPos 6 4 + + let ident = + (pos, parseTree) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynValSig(SynValSig(ident = SynIdent(ident = valIdent))) -> Some valIdent.idText + | _ -> None) + + match ident with + | Some "Foo" -> () + | _ -> failwith "Did not visit SynValSig in SynMemberSig.Member" + +[] +let ``tryPick picks the first matching node`` () = + let source = """ +module M + +module N = + module O = + module P = begin end +""" + + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let ``module`` = + (mkPos 6 28, parseTree) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longIdent))) -> + Some(longIdent |> List.map (fun ident -> ident.idText)) + | _ -> None) + + Assert.Equal(Some ["N"], ``module``) + +[] +let ``tryPick falls back to the nearest matching node to the left if pos is out of range`` () = + let source = """ +module M + +module N = + module O = + module P = begin end +""" + + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let ``module`` = + (mkPos 7 30, parseTree) + ||> ParsedInput.tryPick (fun _path node -> + match node with + | SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longIdent))) -> + Some(longIdent |> List.map (fun ident -> ident.idText)) + | _ -> None) + + Assert.Equal(Some ["N"], ``module``) + +[] +let ``tryPickLast picks the last matching node`` () = + let source = """ +module M + +module N = + module O = + module P = begin end +""" + + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let ``module`` = + (mkPos 6 28, parseTree) + ||> ParsedInput.tryPickLast (fun _path node -> + match node with + | SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longIdent))) -> + Some(longIdent |> List.map (fun ident -> ident.idText)) + | _ -> None) + + Assert.Equal(Some ["P"], ``module``) + +[] +let ``tryPickLast falls back to the nearest matching node to the left if pos is out of range`` () = + let source = """ +module M + +module N = + module O = + module P = begin end +""" + + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let ``module`` = + (mkPos 7 30, parseTree) + ||> ParsedInput.tryPickLast (fun _path node -> + match node with + | SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longIdent))) -> + Some(longIdent |> List.map (fun ident -> ident.idText)) + | _ -> None) + + Assert.Equal(Some ["P"], ``module``) + +[] +let ``exists returns true for the first matching node`` () = + let source = """ +module M + +module N = + module O = + module P = begin end +""" + + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let mutable start = 0, 0 + + let found = + (mkPos 6 28, parseTree) + ||> ParsedInput.exists (fun _path node -> + match node with + | SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longIdent))) -> + start <- node.Range.StartLine, node.Range.StartColumn + true + | _ -> false) + + Assert.True found + Assert.Equal((4, 0), start) + +[] +let ``exists falls back to the nearest matching node to the left if pos is out of range`` () = + let source = """ +module M + +module N = + module O = + module P = begin end +""" + + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let mutable start = 0, 0 + + let found = + (mkPos 7 30, parseTree) + ||> ParsedInput.exists (fun _path node -> + match node with + | SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longIdent))) -> + start <- node.Range.StartLine, node.Range.StartColumn + true + | _ -> false) + + Assert.True found + Assert.Equal((4, 0), start) + +[] +let ``tryNode picks the last node containing the given position`` () = + let source = """ +module M + +module N = + module O = + module P = begin end +""" + + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let ``module`` = + parseTree + |> ParsedInput.tryNode (mkPos 6 28) + |> Option.bind (fun (node, _path) -> + match node with + | SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longIdent))) -> + Some(longIdent |> List.map (fun ident -> ident.idText)) + | _ -> None) + + Assert.Equal(Some ["P"], ``module``) + +[] +let ``tryNode returns None if no node contains the given position`` () = + let source = """ +module M + +module N = + module O = + module P = begin end +""" + + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let ``module`` = parseTree |> ParsedInput.tryNode (mkPos 6 30) + + Assert.Equal(None, ``module``) + +[] +let ``fold traverses nodes in order`` () = + let source = """ +module M + +module N = + module O = + module P = begin end + +module Q = + module R = + module S = begin end +""" + + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let modules = + ([], parseTree) + ||> ParsedInput.fold (fun acc _path node -> + match node with + | SyntaxNode.SynModuleOrNamespace(SynModuleOrNamespace(longId = longIdent)) + | SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longIdent))) -> + (longIdent |> List.map (fun ident -> ident.idText)) :: acc + | _ -> acc) + + Assert.Equal( + [["M"]; ["N"]; ["O"]; ["P"]; ["Q"]; ["R"]; ["S"]], + List.rev modules) + +[] +let ``foldWhile traverses nodes in order`` () = + let source = """ +module M + +module N = + module O = + module P = begin end + +module Q = + module R = + module S = begin end +""" + + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let modules = + ([], parseTree) + ||> ParsedInput.foldWhile (fun acc _path node -> + match node with + | SyntaxNode.SynModuleOrNamespace(SynModuleOrNamespace(longId = longIdent)) + | SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longIdent))) -> + Some((longIdent |> List.map (fun ident -> ident.idText)) :: acc) + | _ -> Some acc) + + Assert.Equal( + [["M"]; ["N"]; ["O"]; ["P"]; ["Q"]; ["R"]; ["S"]], + List.rev modules) + +[] +let ``foldWhile traverses nodes in order until the folder returns None`` () = + let source = """ +module M + +module N = + module O = + module P = begin end + +module Q = + module R = + module S = begin end +""" + + let parseTree = parseSourceCode ("C:\\test.fs", source) + + let modules = + ([], parseTree) + ||> ParsedInput.foldWhile (fun acc _path node -> + if posGt node.Range.Start (mkPos 7 0) then None + else + match node with + | SyntaxNode.SynModuleOrNamespace(SynModuleOrNamespace(longId = longIdent)) + | SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longIdent))) -> + Some((longIdent |> List.map (fun ident -> ident.idText)) :: acc) + | _ -> Some acc) + + Assert.Equal( + [["M"]; ["N"]; ["O"]; ["P"]], + List.rev modules) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl index 4f43f18a283..eeea1540744 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl @@ -672,12 +672,14 @@ Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Microsoft.FSharp.Contro Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Microsoft.FSharp.Control.FSharpAsync`1[T] Scan[T](Microsoft.FSharp.Core.FSharpFunc`2[TMsg,Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Control.FSharpAsync`1[T]]], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Microsoft.FSharp.Control.FSharpHandler`1[System.Exception] Error Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg] Start(Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg],Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken]) +Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg] StartImmediate(Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg],Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken]) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Microsoft.FSharp.Core.FSharpOption`1[TReply] TryPostAndReply[TReply](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Control.FSharpAsyncReplyChannel`1[TReply],TMsg], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: TReply PostAndReply[TReply](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Control.FSharpAsyncReplyChannel`1[TReply],TMsg], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void .ctor(Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg],Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken]) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void Dispose() Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void Post(TMsg) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void Start() +Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void StartImmediate() Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void add_Error(Microsoft.FSharp.Control.FSharpHandler`1[System.Exception]) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void remove_Error(Microsoft.FSharp.Control.FSharpHandler`1[System.Exception]) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void set_DefaultTimeout(Int32) @@ -950,6 +952,7 @@ Microsoft.FSharp.Core.CustomOperationAttribute: System.String JoinConditionWord Microsoft.FSharp.Core.CustomOperationAttribute: System.String Name Microsoft.FSharp.Core.CustomOperationAttribute: System.String get_JoinConditionWord() Microsoft.FSharp.Core.CustomOperationAttribute: System.String get_Name() +Microsoft.FSharp.Core.CustomOperationAttribute: Void .ctor() Microsoft.FSharp.Core.CustomOperationAttribute: Void .ctor(System.String) Microsoft.FSharp.Core.CustomOperationAttribute: Void set_AllowIntoPattern(Boolean) Microsoft.FSharp.Core.CustomOperationAttribute: Void set_IsLikeGroupJoin(Boolean) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl index 9053702b59d..5b8c8858e96 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl @@ -952,6 +952,7 @@ Microsoft.FSharp.Core.CustomOperationAttribute: System.String JoinConditionWord Microsoft.FSharp.Core.CustomOperationAttribute: System.String Name Microsoft.FSharp.Core.CustomOperationAttribute: System.String get_JoinConditionWord() Microsoft.FSharp.Core.CustomOperationAttribute: System.String get_Name() +Microsoft.FSharp.Core.CustomOperationAttribute: Void .ctor() Microsoft.FSharp.Core.CustomOperationAttribute: Void .ctor(System.String) Microsoft.FSharp.Core.CustomOperationAttribute: Void set_AllowIntoPattern(Boolean) Microsoft.FSharp.Core.CustomOperationAttribute: Void set_IsLikeGroupJoin(Boolean) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl index 32481f9c338..5a5008e7218 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl @@ -672,12 +672,14 @@ Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Microsoft.FSharp.Contro Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Microsoft.FSharp.Control.FSharpAsync`1[T] Scan[T](Microsoft.FSharp.Core.FSharpFunc`2[TMsg,Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Control.FSharpAsync`1[T]]], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Microsoft.FSharp.Control.FSharpHandler`1[System.Exception] Error Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg] Start(Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg],Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken]) +Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg] StartImmediate(Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg],Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken]) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Microsoft.FSharp.Core.FSharpOption`1[TReply] TryPostAndReply[TReply](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Control.FSharpAsyncReplyChannel`1[TReply],TMsg], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: TReply PostAndReply[TReply](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Control.FSharpAsyncReplyChannel`1[TReply],TMsg], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void .ctor(Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg],Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken]) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void Dispose() Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void Post(TMsg) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void Start() +Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void StartImmediate() Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void add_Error(Microsoft.FSharp.Control.FSharpHandler`1[System.Exception]) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void remove_Error(Microsoft.FSharp.Control.FSharpHandler`1[System.Exception]) Microsoft.FSharp.Control.FSharpMailboxProcessor`1[TMsg]: Void set_DefaultTimeout(Int32) @@ -951,6 +953,7 @@ Microsoft.FSharp.Core.CustomOperationAttribute: System.String JoinConditionWord Microsoft.FSharp.Core.CustomOperationAttribute: System.String Name Microsoft.FSharp.Core.CustomOperationAttribute: System.String get_JoinConditionWord() Microsoft.FSharp.Core.CustomOperationAttribute: System.String get_Name() +Microsoft.FSharp.Core.CustomOperationAttribute: Void .ctor() Microsoft.FSharp.Core.CustomOperationAttribute: Void .ctor(System.String) Microsoft.FSharp.Core.CustomOperationAttribute: Void set_AllowIntoPattern(Boolean) Microsoft.FSharp.Core.CustomOperationAttribute: Void set_IsLikeGroupJoin(Boolean) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl index dd392757335..12f8380fbfb 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl @@ -953,6 +953,7 @@ Microsoft.FSharp.Core.CustomOperationAttribute: System.String JoinConditionWord Microsoft.FSharp.Core.CustomOperationAttribute: System.String Name Microsoft.FSharp.Core.CustomOperationAttribute: System.String get_JoinConditionWord() Microsoft.FSharp.Core.CustomOperationAttribute: System.String get_Name() +Microsoft.FSharp.Core.CustomOperationAttribute: Void .ctor() Microsoft.FSharp.Core.CustomOperationAttribute: Void .ctor(System.String) Microsoft.FSharp.Core.CustomOperationAttribute: Void set_AllowIntoPattern(Boolean) Microsoft.FSharp.Core.CustomOperationAttribute: Void set_IsLikeGroupJoin(Boolean) diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index d021fecc953..6d1eb1b0707 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -27,6 +27,7 @@ open TestFramework open System.Runtime.CompilerServices open System.Runtime.InteropServices +open FSharp.Compiler.CodeAnalysis module rec Compiler = @@ -920,7 +921,7 @@ module rec Compiler = CompilerAssert.TypeCheck(options, fileName, source) | _ -> failwith "Typecheck only supports F#" - let typecheckProject enablePartialTypeChecking (cUnit: CompilationUnit) : FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults = + let typecheckProject enablePartialTypeChecking useTransparentCompiler (cUnit: CompilationUnit) : FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults = match cUnit with | FS fsSource -> let options = fsSource.Options |> Array.ofList @@ -938,7 +939,8 @@ module rec Compiler = |> async.Return let sourceFiles = Array.map fst sourceFiles - CompilerAssert.TypeCheckProject(options, sourceFiles, getSourceText, enablePartialTypeChecking) + + CompilerAssert.TypeCheckProject(options, sourceFiles, getSourceText, enablePartialTypeChecking, useTransparentCompiler) | _ -> failwith "Typecheck only supports F#" let run (result: CompilationResult) : CompilationResult = diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs index 1dcbcb846ff..7951ba31d5d 100644 --- a/tests/FSharp.Test.Utilities/CompilerAssert.fs +++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs @@ -11,6 +11,7 @@ open System.Reflection open FSharp.Compiler.Interactive.Shell open FSharp.Compiler.IO open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.CodeAnalysis.ProjectSnapshot open FSharp.Compiler.Diagnostics open FSharp.Compiler.Text #if NETCOREAPP @@ -258,7 +259,8 @@ and Compilation = module rec CompilerAssertHelpers = - let checker = FSharpChecker.Create(suggestNamesForErrors=true) + let useTransparentCompiler = FSharp.Compiler.CompilerConfig.FSharpExperimentalFeaturesEnabledAutomatically + let checker = FSharpChecker.Create(suggestNamesForErrors=true, useTransparentCompiler=useTransparentCompiler) // Unlike C# whose entrypoint is always string[] F# can make an entrypoint with 0 args, or with an array of string[] let mkDefaultArgs (entryPoint:MethodBase) : obj[] = [| @@ -386,7 +388,7 @@ module rec CompilerAssertHelpers = let name = match nameOpt with | Some name -> name - | _ -> tryCreateTemporaryFileName() + | _ -> tryCreateTemporaryFileNameInDirectory(outputDirectory) let outputFilePath = Path.ChangeExtension (Path.Combine(outputDirectory.FullName, name), if isExe then ".exe" else ".dll") disposals.Add(disposeFile outputFilePath) @@ -886,14 +888,31 @@ Updated automatically, please check diffs in your pull request, changes must be static member TypeCheckSingleError (source: string) (expectedSeverity: FSharpDiagnosticSeverity) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) = CompilerAssert.TypeCheckWithErrors source [| expectedSeverity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |] - static member TypeCheckProject(options: string array, sourceFiles: string array, getSourceText, enablePartialTypeChecking) : FSharpCheckProjectResults = - let checker = FSharpChecker.Create(documentSource = DocumentSource.Custom getSourceText, enablePartialTypeChecking = enablePartialTypeChecking) + static member TypeCheckProject(options: string array, sourceFiles: string array, getSourceText, enablePartialTypeChecking, useTransparentCompiler) : FSharpCheckProjectResults = + let checker = FSharpChecker.Create(documentSource = DocumentSource.Custom getSourceText, enablePartialTypeChecking = enablePartialTypeChecking, useTransparentCompiler = useTransparentCompiler) let defaultOptions = defaultProjectOptions TargetFramework.Current let projectOptions = { defaultOptions with OtherOptions = Array.append options defaultOptions.OtherOptions; SourceFiles = sourceFiles } - checker.ParseAndCheckProject(projectOptions) + if useTransparentCompiler then + let getFileSnapshot _ fileName = + async.Return + (FSharpFileSnapshot( + FileName = fileName, + Version = "1", + GetSource = fun () -> task { + match! getSourceText fileName with + | Some source -> return SourceTextNew.ofISourceText source + | None -> return failwith $"couldn't get source for {fileName}" + } + )) + + let snapshot = FSharpProjectSnapshot.FromOptions(projectOptions, getFileSnapshot) |> Async.RunSynchronously + + checker.ParseAndCheckProject(snapshot) + else + checker.ParseAndCheckProject(projectOptions) |> Async.RunImmediate - + static member CompileExeWithOptions(options, (source: SourceCodeFileKind)) = compile true options source (fun (errors, _, _) -> if errors.Length > 0 then diff --git a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj index 6867d180ae9..5cfcba98ca7 100644 --- a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj +++ b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj @@ -73,6 +73,18 @@ + + + + + + + + + + + + @@ -88,6 +100,7 @@ + diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs index 73f7fd1f0e4..54c00ebe544 100644 --- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs +++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs @@ -25,6 +25,7 @@ open System.Threading.Tasks open System.Xml open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.CodeAnalysis.ProjectSnapshot open FSharp.Compiler.Diagnostics open FSharp.Compiler.Text @@ -41,7 +42,7 @@ let private projectRoot = "test-projects" let private defaultFunctionName = "f" type Reference = { - Name: string + Name: string Version: string option } module ReferenceHelpers = @@ -68,13 +69,13 @@ module ReferenceHelpers = } |> String.concat "\n" - let runtimeList = lazy ( + let runtimeList = lazy ( // You can see which versions of the .NET runtime are currently installed with the following command. let psi = ProcessStartInfo("dotnet", "--list-runtimes", RedirectStandardOutput = true, UseShellExecute = false) let proc = Process.Start(psi) - proc.WaitForExit() + proc.WaitForExit(1000) |> ignore let output = seq { @@ -92,7 +93,8 @@ module ReferenceHelpers = { Name = matches.Groups.[1].Value Version = version - Path = DirectoryInfo(Path.Combine(matches.Groups[3].Value, version)) })) + Path = DirectoryInfo(Path.Combine(matches.Groups[3].Value, version)) }) + |> Seq.toList) let getFrameworkReference (reference: Reference) = @@ -540,10 +542,45 @@ module ProjectOperations = filePath |> project.FindByPath |> renderSourceFile project - |> SourceText.ofString + |> SourceTextNew.ofString + + let internal getFileSnapshot (project: SyntheticProject) _options (path: string) = + async { + let project, filePath = + if path.EndsWith(".fsi") then + let implFilePath = path[..path.Length - 2] + let p, f = project.FindInAllProjectsByPath implFilePath + p, getSignatureFilePath p f + else + let p, f = project.FindInAllProjectsByPath path + p, getFilePath p f + + let source = getSourceText project path + use md5 = System.Security.Cryptography.MD5.Create() + let inputBytes = Encoding.UTF8.GetBytes(source.ToString()) + let hash = md5.ComputeHash(inputBytes) |> Array.map (fun b -> b.ToString("X2")) |> String.concat "" + + return FSharpFileSnapshot( + FileName = filePath, + Version = hash, + GetSource = fun () -> source |> Task.FromResult + ) + } + + let checkFileWithTransparentCompiler fileId (project: SyntheticProject) (checker: FSharpChecker) = + async { + let file = project.Find fileId + let absFileName = getFilePath project file + let options = project.GetProjectOptions checker + let! projectSnapshot = FSharpProjectSnapshot.FromOptions(options, getFileSnapshot project) + return! checker.ParseAndCheckFileInProject(absFileName, projectSnapshot) + } let checkFile fileId (project: SyntheticProject) (checker: FSharpChecker) = - checkFileWithIncrementalBuilder fileId project checker + (if checker.UsesTransparentCompiler then + checkFileWithTransparentCompiler + else + checkFileWithIncrementalBuilder) fileId project checker let getTypeCheckResult (parseResults: FSharpParseFileResults, checkResults: FSharpCheckFileAnswer) = Assert.True(not parseResults.ParseHadErrors) @@ -680,7 +717,7 @@ module ProjectOperations = module Helpers = - let getSymbolUse fileName (source: string) (symbolName: string) options (checker: FSharpChecker) = + let internal getSymbolUse fileName (source: string) (symbolName: string) snapshot (checker: FSharpChecker) = async { let lines = source.Split '\n' |> Seq.skip 1 // module definition let lineNumber, fullLine, colAtEndOfNames = @@ -694,8 +731,7 @@ module Helpers = |> Seq.tryPick id |> Option.defaultValue (-1, "", -1) - let! results = checker.ParseAndCheckFileInProject( - fileName, 0, SourceText.ofString source, options) + let! results = checker.ParseAndCheckFileInProject(fileName, snapshot) let typeCheckResults = getTypeCheckResult results @@ -706,18 +742,23 @@ module Helpers = failwith $"No symbol found in {fileName} at {lineNumber}:{colAtEndOfNames}\nFile contents:\n\n{source}\n") } - let singleFileChecker source = + let internal singleFileChecker source = let fileName = "test.fs" - let getSource _ = source |> SourceText.ofString |> Some |> async.Return + let getSource _ fileName = + FSharpFileSnapshot( + FileName = fileName, + Version = "1", + GetSource = fun () -> source |> SourceTextNew.ofString |> Task.FromResult ) + |> async.Return let checker = FSharpChecker.Create( keepAllBackgroundSymbolUses = false, enableBackgroundItemKeyStoreAndSemanticClassification = true, enablePartialTypeChecking = true, captureIdentifiersWhenParsing = true, - documentSource = DocumentSource.Custom getSource) + useTransparentCompiler = true) let options = let baseOptions, _ = @@ -739,7 +780,9 @@ module Helpers = OriginalLoadReferences = [] Stamp = None } - fileName, options, checker + let snapshot = FSharpProjectSnapshot.FromOptions(options, getSource) |> Async.RunSynchronously + + fileName, snapshot, checker open Helpers @@ -757,8 +800,9 @@ let SaveAndCheckProject project checker = do! saveProject project true checker let options = project.GetProjectOptions checker + let! snapshot = FSharpProjectSnapshot.FromOptions(options, getFileSnapshot project) - let! results = checker.ParseAndCheckProject(options) + let! results = checker.ParseAndCheckProject(snapshot) if not (Array.isEmpty results.Diagnostics || project.SkipInitialCheck) then failwith $"Project {project.Name} failed initial check: \n%A{results.Diagnostics}" @@ -778,6 +822,8 @@ let SaveAndCheckProject project checker = Cursor = None } } +type MoveFileDirection = Up | Down + type ProjectWorkflowBuilder ( initialProject: SyntheticProject, @@ -791,7 +837,7 @@ type ProjectWorkflowBuilder ?autoStart ) = - let useTransparentCompiler = defaultArg useTransparentCompiler false + let useTransparentCompiler = defaultArg useTransparentCompiler FSharp.Compiler.CompilerConfig.FSharpExperimentalFeaturesEnabledAutomatically let useGetSource = not useTransparentCompiler && defaultArg useGetSource false let useChangeNotifications = not useTransparentCompiler && defaultArg useChangeNotifications false let autoStart = defaultArg autoStart true @@ -800,7 +846,7 @@ type ProjectWorkflowBuilder let mutable activity = None let mutable tracerProvider = None - let getSource f = f |> getSourceText latestProject |> Some |> async.Return + let getSource f = f |> getSourceText latestProject :> ISourceText |> Some |> async.Return let checker = defaultArg @@ -811,7 +857,9 @@ type ProjectWorkflowBuilder enablePartialTypeChecking = true, captureIdentifiersWhenParsing = true, documentSource = (if useGetSource then DocumentSource.Custom getSource else DocumentSource.FileSystem), - useSyntaxTreeCache = defaultArg useSyntaxTreeCache false)) + useSyntaxTreeCache = defaultArg useSyntaxTreeCache false, + useTransparentCompiler = useTransparentCompiler + )) let mapProjectAsync f workflow = async { @@ -859,7 +907,9 @@ type ProjectWorkflowBuilder member this.DeleteProjectDir() = if Directory.Exists initialProject.ProjectDir then - Directory.Delete(initialProject.ProjectDir, true) + try + Directory.Delete(initialProject.ProjectDir, true) + with _ -> () member this.Execute(workflow: Async) = try @@ -1000,6 +1050,30 @@ type ProjectWorkflowBuilder return { ctx with Signatures = ctx.Signatures.Add(fileId, newSignature) } } + [] + member this.MoveFile(workflow: Async, fileId: string, count, direction: MoveFileDirection) = + + workflow + |> mapProject (fun project -> + let index = + project.SourceFiles + |> List.tryFindIndex (fun f -> f.Id = fileId) + |> Option.defaultWith (fun () -> failwith $"File {fileId} not found") + + let dir = if direction = Up then -1 else 1 + let newIndex = index + count * dir + + if newIndex < 0 || newIndex > project.SourceFiles.Length - 1 then + failwith $"Cannot move file {fileId} {count} times {direction} as it would be out of bounds" + + let file = project.SourceFiles.[index] + let newFiles = + project.SourceFiles + |> List.filter (fun f -> f.Id <> fileId) + |> List.insertAt newIndex file + + { project with SourceFiles = newFiles }) + /// Find a symbol using the provided range, mimicking placing a cursor on it in IDE scenarios [] member this.PlaceCursor(workflow: Async, fileId, line, colAtEndOfNames, fullLine, symbolNames) = @@ -1025,8 +1099,9 @@ type ProjectWorkflowBuilder let project, file = ctx.Project.FindInAllProjects fileId let fileName = project.ProjectDir ++ file.FileName let source = renderSourceFile project file - let options= project.GetProjectOptions checker - return! getSymbolUse fileName source symbolName options checker + let options = project.GetProjectOptions checker + let! snapshot = FSharpProjectSnapshot.FromOptions(options, getFileSnapshot ctx.Project) + return! getSymbolUse fileName source symbolName snapshot checker } /// Find a symbol by finding the first occurrence of the symbol name in the file @@ -1085,7 +1160,10 @@ type ProjectWorkflowBuilder [ for p, f in ctx.Project.GetAllFiles() do let options = p.GetProjectOptions checker for fileName in [getFilePath p f; if f.SignatureFile <> No then getSignatureFilePath p f] do - checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol, fastCheck = true) ] + async { + let! snapshot = FSharpProjectSnapshot.FromOptions(options, getFileSnapshot ctx.Project) + return! checker.FindBackgroundReferencesInFile(fileName, snapshot, symbolUse.Symbol) + } ] |> Async.Parallel results |> Seq.collect id |> Seq.toList |> processResults @@ -1210,7 +1288,7 @@ type SyntheticProject with projectDir ++ node.Attributes["Include"].InnerText ] |> List.partition (fun path -> path.EndsWith ".fsi") let signatureFiles = set signatureFiles - + let parseReferences refType = [ for node in fsproj.DocumentElement.SelectNodes($"//{refType}") do { Name = node.Attributes["Include"].InnerText diff --git a/tests/FSharp.Test.Utilities/TestFramework.fs b/tests/FSharp.Test.Utilities/TestFramework.fs index e5af95432b0..f7ec7f48001 100644 --- a/tests/FSharp.Test.Utilities/TestFramework.fs +++ b/tests/FSharp.Test.Utilities/TestFramework.fs @@ -28,12 +28,11 @@ let tryCreateTemporaryFileName () = filePath // Create a temporaryFileName -- newGuid is random --- there is no point validating the file alread exists because: threading and Path.ChangeExtension() is commonly used after this API -let tryCreateTemporaryFileNameInDirectory (directory) = +let tryCreateTemporaryFileNameInDirectory (directory: DirectoryInfo) = let fileName = ("Temp-" + Guid.NewGuid().ToString() + ".tmp").Replace('-', '_') - let filePath = Path.Combine(directory, fileName) + let filePath = Path.Combine(directory.FullName, fileName) filePath - [] module Commands = diff --git a/tests/FSharp.Test.Utilities/Utilities.fs b/tests/FSharp.Test.Utilities/Utilities.fs index a2a84a5b725..d434d837485 100644 --- a/tests/FSharp.Test.Utilities/Utilities.fs +++ b/tests/FSharp.Test.Utilities/Utilities.fs @@ -15,6 +15,10 @@ open Microsoft.CodeAnalysis.CSharp open TestFramework open NUnit.Framework open System.Collections.Generic +open FSharp.Compiler.CodeAnalysis +open Newtonsoft.Json +open Newtonsoft.Json.Linq + type TheoryForNETCOREAPPAttribute() = inherit Xunit.TheoryAttribute() @@ -104,12 +108,12 @@ module Utilities = let outputLines = StringBuilder() let errorLines = StringBuilder() - do redirector.OutputProduced.Add (fun line -> outputLines.AppendLine line |>ignore) - do redirector.ErrorProduced.Add(fun line -> errorLines.AppendLine line |>ignore) + do redirector.OutputProduced.Add (fun line -> lock outputLines <| fun () -> outputLines.AppendLine line |>ignore) + do redirector.ErrorProduced.Add(fun line -> lock errorLines <| fun () -> errorLines.AppendLine line |>ignore) - member _.Output () = outputLines.ToString() + member _.Output () = lock outputLines outputLines.ToString - member _.ErrorOutput () = errorLines.ToString() + member _.ErrorOutput () = lock errorLines errorLines.ToString interface IDisposable with member _.Dispose() = (redirector :> IDisposable).Dispose() @@ -381,3 +385,10 @@ An error occurred getting netcoreapp references: %A{e} | TargetFramework.NetStandard20 -> netStandard20Files.Value |> Seq.toArray | TargetFramework.NetCoreApp31 -> [||] //ToDo --- Perhaps NetCoreApp31Files | TargetFramework.Current -> currentReferences + + +module internal FSharpProjectSnapshotSerialization = + + let serializeSnapshotToJson (snapshot: FSharpProjectSnapshot) = + + JsonConvert.SerializeObject(snapshot, Formatting.Indented, new JsonSerializerSettings(ReferenceLoopHandling = ReferenceLoopHandling.Ignore)) \ No newline at end of file diff --git a/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/Async.fs b/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/Async.fs index 704b0723c94..4e7028e692e 100644 --- a/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/Async.fs +++ b/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/Async.fs @@ -8,7 +8,7 @@ open BenchmarkDotNet.Attributes [] type AsyncWhileMemoryBench() = - [] + [] member val Length = 0 with get, set [] diff --git a/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/Benchmarks.fs b/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/Benchmarks.fs index 366efa97439..a081437e1f0 100644 --- a/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/Benchmarks.fs +++ b/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/Benchmarks.fs @@ -1,8 +1,3 @@ -(* -msbuild tests\fsharp\perf\tasks\FS\TaskPerf.fsproj /p:Configuration=Release -dotnet artifacts\bin\TaskPerf\Release\netcoreapp2.1\TaskPerf.dll -*) - namespace TaskPerf open BenchmarkDotNet.Running @@ -10,9 +5,7 @@ open BenchmarkDotNet.Running module Main = [] - let main argv = + let main _ = printfn "Running benchmarks..." - //let results = BenchmarkRunner.Run() - //let results = BenchmarkRunner.Run() - let results = BenchmarkRunner.Run() + let _ = BenchmarkRunner.Run() 0 diff --git a/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/CS/MicroPerfCSharp.cs b/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/CS/MicroPerfCSharp.cs index 409ed07ac55..93d5833555d 100644 --- a/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/CS/MicroPerfCSharp.cs +++ b/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/CS/MicroPerfCSharp.cs @@ -4,7 +4,7 @@ public class MicroPerfCSharp { // - // FSharp will not inline the code so we shouldn't eiter. + // FSharp will not inline the code so we shouldn't either. // [MethodImpl(MethodImplOptions.NoInlining)] public static int Cond(int x) diff --git a/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/CS/MicroPerfCSharp.csproj b/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/CS/MicroPerfCSharp.csproj index 96ac25da87b..50bba8f6f23 100644 --- a/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/CS/MicroPerfCSharp.csproj +++ b/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/CS/MicroPerfCSharp.csproj @@ -6,11 +6,10 @@ 8.0 - - - - - + + + $(NoWarn);CS1591 + diff --git a/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/Collections.fs b/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/Collections.fs index 1fdacc37fd9..fa6178e6778 100644 --- a/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/Collections.fs +++ b/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/Collections.fs @@ -1,10 +1,6 @@ module Collections open BenchmarkDotNet.Attributes -open BenchmarkDotNet.Running -open BenchmarkDotNet.Configs -open BenchmarkDotNet.Diagnosers -open System.Runtime.CompilerServices [] [] @@ -15,7 +11,7 @@ type CollectionsBenchmark() = let mutable list = [] let mutable array = [||] - [] + [] member this.Length with get () = length and set (value) = diff --git a/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/MicroPerf.fsproj b/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/MicroPerf.fsproj index 81866aa5676..919c4cc073c 100644 --- a/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/MicroPerf.fsproj +++ b/tests/benchmarks/CompiledCodeBenchmarks/MicroPerf/MicroPerf.fsproj @@ -2,13 +2,6 @@ net8.0 Exe - - $(NoWarn);NU1505 true $(OtherFlags) --nowarn:1204 @@ -16,13 +9,6 @@ $(OtherFlags) --nowarn:57 $(OtherFlags) --langversion:preview $(OtherFlags) --define:PREVIEW - - - @@ -30,6 +16,7 @@ + diff --git a/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerf/TaskPerf.fs b/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerf/TaskPerf.fs index 7f03c4d636b..6f89f4fd6eb 100644 --- a/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerf/TaskPerf.fs +++ b/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerf/TaskPerf.fs @@ -1,19 +1,11 @@ -(* -msbuild tests\benchmarks\CompiledCodeBenchmarks\TaskPerf\TaskPerf\TaskPerf.fsproj /p:Configuration=Release -dotnet artifacts\bin\TaskPerf\Release\net7.0\TaskPerf.dll -*) - namespace TaskPerf -//open FSharp.Control.Tasks open System -open System.Diagnostics open System.Threading.Tasks open System.IO open BenchmarkDotNet.Attributes open BenchmarkDotNet.Running open TaskBuilderTasks //.ContextSensitive // TaskBuilder.fs extension members -//open FSharp.Control.ContextSensitiveTasks // the default open FSharp.Control // AsyncSeq open Tests.SyncBuilder open BenchmarkDotNet.Configs diff --git a/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerf/TaskPerf.fsproj b/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerf/TaskPerf.fsproj index 4d29d42c536..9706167ff62 100644 --- a/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerf/TaskPerf.fsproj +++ b/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerf/TaskPerf.fsproj @@ -3,13 +3,6 @@ net8.0 Exe - - NU1505 true $(OtherFlags) --nowarn:1204 @@ -23,9 +16,6 @@ - @@ -37,14 +27,9 @@ - - - - + diff --git a/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerfCSharp/TaskPerfCSharp.csproj b/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerfCSharp/TaskPerfCSharp.csproj index 323d4d5ce6f..d23714e40f2 100644 --- a/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerfCSharp/TaskPerfCSharp.csproj +++ b/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerfCSharp/TaskPerfCSharp.csproj @@ -1,13 +1,18 @@  - net7.0 + net8.0 Library 8.0 + + + $(NoWarn);CS1591 + + - + diff --git a/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerfPreviousCompiler/TaskPerfPreviousCompiler.fsproj b/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerfPreviousCompiler/TaskPerfPreviousCompiler.fsproj deleted file mode 100644 index b71c47ac821..00000000000 --- a/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerfPreviousCompiler/TaskPerfPreviousCompiler.fsproj +++ /dev/null @@ -1,30 +0,0 @@ - - - - net8.0 - Exe - true - $(OtherFlags) --define:ASYNC_PERF - true - - C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\FSharp - fsc.exe - - - - - - - - - - - - - - - - - - - diff --git a/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerfPreviousCompiler/defs.fs b/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerfPreviousCompiler/defs.fs deleted file mode 100644 index 42cea70022c..00000000000 --- a/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerfPreviousCompiler/defs.fs +++ /dev/null @@ -1,14 +0,0 @@ - -namespace Tests - -open System - -#if !PREVIEW - -[] -[] -type InlineIfLambdaAttribute() = - inherit Attribute() - -#endif - diff --git a/tests/benchmarks/FCSBenchmarks/BenchmarkComparison/HistoricalBenchmark.fsproj b/tests/benchmarks/FCSBenchmarks/BenchmarkComparison/HistoricalBenchmark.fsproj index a477f61af81..2534ba292b5 100644 --- a/tests/benchmarks/FCSBenchmarks/BenchmarkComparison/HistoricalBenchmark.fsproj +++ b/tests/benchmarks/FCSBenchmarks/BenchmarkComparison/HistoricalBenchmark.fsproj @@ -5,13 +5,6 @@ net8.0 true Release - - $(NoWarn);NU1505 diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs index 3b44c1d37bf..d7d643ab915 100644 --- a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs @@ -6,6 +6,7 @@ open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.Text open FSharp.Compiler.Diagnostics open FSharp.Test.ProjectGeneration +open BenchmarkDotNet.Engines [] @@ -152,10 +153,7 @@ type NoFileSystemCheckerBenchmark() = let mutable benchmark : ProjectWorkflowBuilder = Unchecked.defaultof<_> [] - member val UseGetSource = true with get,set - - [] - member val UseChangeNotifications = true with get,set + member val UseInMemoryDocuments = true with get,set [] member val EmptyCache = true with get,set @@ -165,8 +163,8 @@ type NoFileSystemCheckerBenchmark() = benchmark <- ProjectWorkflowBuilder( project, - useGetSource = this.UseGetSource, - useChangeNotifications = this.UseChangeNotifications).CreateBenchmarkBuilder() + useGetSource = this.UseInMemoryDocuments, + useChangeNotifications = this.UseInMemoryDocuments).CreateBenchmarkBuilder() [] member this.EditFirstFile_OnlyInternalChange() = @@ -178,15 +176,14 @@ type NoFileSystemCheckerBenchmark() = member this.ExampleWorkflow() = use _ = Activity.start "Benchmark" [ - "UseGetSource", this.UseGetSource.ToString() - "UseChangeNotifications", this.UseChangeNotifications.ToString() + "UseInMemoryDocuments", this.UseInMemoryDocuments.ToString() ] let first = "File001" let middle = $"File%03d{size / 2}" let last = $"File%03d{size}" - if this.UseGetSource && this.UseChangeNotifications then + if this.UseInMemoryDocuments then benchmark { updateFile first updatePublicSurface @@ -221,3 +218,215 @@ type NoFileSystemCheckerBenchmark() = [] member this.Cleanup() = benchmark.DeleteProjectDir() + + + +type TestProjectType = + | DependencyChain = 1 + | DependentGroups = 2 + | ParallelGroups = 3 + + +[] +[] +[] +[] +type TransparentCompilerBenchmark() = + + let size = 30 + + let groups = 6 + let filesPerGroup = size / groups + let somethingToCompile = File.ReadAllText (__SOURCE_DIRECTORY__ ++ "SomethingToCompileSmaller.fs") + + let projects = Map [ + + TestProjectType.DependencyChain, + SyntheticProject.Create("SingleDependencyChain", [| + sourceFile $"File%03d{0}" [] + for i in 1..size do + { sourceFile $"File%03d{i}" [$"File%03d{i-1}"] with ExtraSource = somethingToCompile } + |]) + + TestProjectType.DependentGroups, + SyntheticProject.Create("GroupDependenciesProject", [| + for group in 1..groups do + for i in 1..filesPerGroup do + { sourceFile $"G{group}_F%03d{i}" [ + if group > 1 then $"G1_F%03d{1}" + if i > 1 then $"G{group}_F%03d{i - 1}" ] + with ExtraSource = somethingToCompile } + |]) + + TestProjectType.ParallelGroups, + SyntheticProject.Create("ParallelGroupsProject", [| + for group in 1..groups do + for i in 1..filesPerGroup do + { sourceFile $"G{group}_F%03d{i}" [ + if group > 1 then + for i in 1..filesPerGroup do + $"G{group-1}_F%03d{i}" ] + with ExtraSource = somethingToCompile } + |]) + ] + + let mutable benchmark : ProjectWorkflowBuilder = Unchecked.defaultof<_> + + member val UseGetSource = true with get,set + + member val UseChangeNotifications = true with get,set + + //[] + member val EmptyCache = false with get,set + + [] + member val UseTransparentCompiler = true with get,set + + [] + member val ProjectType = TestProjectType.ParallelGroups with get,set + + member this.Project = projects[this.ProjectType] + + [] + member this.Setup() = + benchmark <- + ProjectWorkflowBuilder( + this.Project, + useGetSource = this.UseGetSource, + useChangeNotifications = this.UseChangeNotifications, + useTransparentCompiler = this.UseTransparentCompiler, + runTimeout = 15_000).CreateBenchmarkBuilder() + + [] + member this.EditFirstFile_OnlyInternalChange() = + if this.EmptyCache then + benchmark.Checker.InvalidateAll() + benchmark.Checker.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients() + + [] + member this.ExampleWorkflow() = + + use _ = Activity.start "Benchmark" [ + "UseTransparentCompiler", this.UseTransparentCompiler.ToString() + ] + + let first = this.Project.SourceFiles[0].Id + let middle = this.Project.SourceFiles[size / 2].Id + let last = this.Project.SourceFiles |> List.last |> fun f -> f.Id + + benchmark { + updateFile first updatePublicSurface + checkFile first expectSignatureChanged + checkFile last expectSignatureChanged + updateFile middle updatePublicSurface + checkFile last expectOk + addFileAbove middle (sourceFile "addedFile" [first]) + updateFile middle (addDependency "addedFile") + checkFile middle expectSignatureChanged + checkFile last expectOk + } + + [] + member this.Cleanup() = + benchmark.DeleteProjectDir() + + +[] +[] +[] +[] +type TransparentCompilerGiraffeBenchmark() = + + let mutable benchmark : ProjectWorkflowBuilder = Unchecked.defaultof<_> + + let rng = System.Random() + + let addComment s = $"{s}\n// {rng.NextDouble().ToString()}" + let prependSlash s = $"/{s}\n// {rng.NextDouble()}" + + let modify (sourceFile: SyntheticSourceFile) = + { sourceFile with Source = addComment sourceFile.Source } + + let break' (sourceFile: SyntheticSourceFile) = + { sourceFile with Source = prependSlash sourceFile.Source } + + let fix (sourceFile: SyntheticSourceFile) = + { sourceFile with Source = sourceFile.Source.Substring 1 } + + [] + member val UseTransparentCompiler = true with get,set + + [] + member val SignatureFiles = true with get,set + + member this.Project = + let projectDir = if this.SignatureFiles then "Giraffe-signatures" else "Giraffe" + + let project = SyntheticProject.CreateFromRealProject (__SOURCE_DIRECTORY__ ++ ".." ++ ".." ++ ".." ++ ".." ++ ".." ++ projectDir ++ "src/Giraffe") + { project with OtherOptions = "--nowarn:FS3520"::project.OtherOptions } + + [] + member this.Setup() = + benchmark <- + ProjectWorkflowBuilder( + this.Project, + useGetSource = true, + useChangeNotifications = true, + useTransparentCompiler = this.UseTransparentCompiler, + runTimeout = 15_000).CreateBenchmarkBuilder() + + //[] + member this.ChangeFirstCheckLast() = + + use _ = Activity.start "Benchmark" [ + "UseTransparentCompiler", this.UseTransparentCompiler.ToString() + ] + + benchmark { + updateFile this.Project.SourceFiles.Head.Id modify + checkFile (this.Project.SourceFiles |> List.last).Id expectOk + } + + //[] + member this.ChangeSecondCheckLast() = + + use _ = Activity.start "Benchmark" [ + "UseTransparentCompiler", this.UseTransparentCompiler.ToString() + ] + + benchmark { + updateFile this.Project.SourceFiles[1].Id modify + checkFile (this.Project.SourceFiles |> List.last).Id expectOk + } + + [] + member this.SomeWorkflow() = + + use _ = Activity.start "Benchmark" [ + "UseTransparentCompiler", this.UseTransparentCompiler.ToString() + ] + + benchmark { + updateFile "Json" modify + checkFile "Json" expectOk + checkFile "ModelValidation" expectOk + updateFile "ModelValidation" modify + checkFile "ModelValidation" expectOk + updateFile "Xml" modify + checkFile "Xml" expectOk + updateFile "ModelValidation" modify + checkFile "ModelValidation" expectOk + + updateFile "Core" break' + checkFile "Core" expectErrors + checkFile "Routing" (if this.SignatureFiles then expectOk else expectErrors) + updateFile "Routing" modify + checkFile "Streaming" (if this.SignatureFiles then expectOk else expectErrors) + checkFile "EndpointRouting" (if this.SignatureFiles then expectOk else expectErrors) + + updateFile "Core" fix + checkFile "Core" expectOk + checkFile "Routing" expectOk + checkFile "Streaming" expectOk + checkFile "EndpointRouting" expectOk + } \ No newline at end of file diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/Benchmarks.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/Benchmarks.fs deleted file mode 100644 index 5f282702bb0..00000000000 --- a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/Benchmarks.fs +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/CompilerServiceBenchmarks.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/CompilerServiceBenchmarks.fs index 679989520c2..4910b2e19eb 100644 --- a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/CompilerServiceBenchmarks.fs +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/CompilerServiceBenchmarks.fs @@ -124,13 +124,13 @@ type CompilerServiceBenchmarks() = |> Some [] - member _.ParsingTypeCheckerFs() = + member _.ParsingCheckExpressionsFs() = let config = getConfig() let results = config.Checker.ParseFile("CheckExpressions.fs", config.Source |> SourceText.toFSharpSourceText, parsingOptions) |> Async.RunSynchronously if results.ParseHadErrors then failwithf $"parse had errors: %A{results.Diagnostics}" - [] - member _.ParsingTypeCheckerFsSetup() = + [] + member _.ParsingCheckExpressionsFsSetup() = let checker = getConfig().Checker checker.InvalidateAll() checker.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients() diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ComputationExpressionBenchmarks.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ComputationExpressionBenchmarks.fs new file mode 100644 index 00000000000..92a7141822d --- /dev/null +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ComputationExpressionBenchmarks.fs @@ -0,0 +1,53 @@ +module FSharp.Benchmarks.ComputationExpressionBenchmarks + +open System.IO +open BenchmarkDotNet.Attributes +open FSharp.Compiler.CodeAnalysis +open FSharp.Test.ProjectGeneration + +[] +let FSharpCategory = "fsharp" + +[] +[] +type ComputationExpressionBenchmarks() = + + let mutable sourceFileName = "" + + [] + member public this.Source + with get () = File.ReadAllText(__SOURCE_DIRECTORY__ ++ "ce" ++ sourceFileName) + and set f = sourceFileName <- f + + member val Benchmark = Unchecked.defaultof<_> with get, set + + member this.setup(project) = + let checker = FSharpChecker.Create() + this.Benchmark <- ProjectWorkflowBuilder(project, checker = checker).CreateBenchmarkBuilder() + saveProject project false checker |> Async.RunSynchronously + + [] + member this.SetupWithSource() = + this.setup + { SyntheticProject.Create() with + SourceFiles = + [ + + { sourceFile "File" [] with + ExtraSource = this.Source + } + ] + OtherOptions = [] + } + + [] + member this.CheckCE() = + this.Benchmark { checkFile "File" expectOk } + + [] + member this.CompileCE() = this.Benchmark { compileWithFSC } diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/DecentlySizedStandAloneFileBenchmark.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/DecentlySizedStandAloneFileBenchmark.fs index f1525cfc734..58dcb885e50 100644 --- a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/DecentlySizedStandAloneFileBenchmark.fs +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/DecentlySizedStandAloneFileBenchmark.fs @@ -1,22 +1,61 @@ namespace FSharp.Compiler.Benchmarks open System.IO -open HistoricalBenchmark +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.Text open BenchmarkDotNet.Attributes -type SingleFileCompilerWithILCacheClearing(file, options) = - inherit SingleFileCompiler(file, options) - - override this.Cleanup() = - base.Cleanup() - FSharp.Compiler.AbstractIL.ILBinaryReader.ClearAllILModuleReaderCache() +type private SingleFileCompilerConfig = + { + Checker : FSharpChecker + Options : FSharpProjectOptions + } [] type DecentlySizedStandAloneFileBenchmark() = - inherit SingleFileCompilerBenchmarkBase( - SingleFileCompilerWithILCacheClearing( - Path.Combine(__SOURCE_DIRECTORY__, "../decentlySizedStandAloneFile.fs"), - OptionsCreationMethod.FromScript - ) - ) + let mutable configOpt : SingleFileCompilerConfig option = None + let filePath = Path.Combine(__SOURCE_DIRECTORY__, "../decentlySizedStandAloneFile.fs") + + let getFileSourceText (filePath : string) = + let text = File.ReadAllText(filePath) + SourceText.ofString text + + let getConfig () = + configOpt + |> Option.defaultWith (fun () -> failwith "Setup not run") + + [] + member _.Setup() = + configOpt <- + match configOpt with + | Some _ -> configOpt + | None -> + let checker = FSharpChecker.Create(projectCacheSize = 200) + let options = + checker.GetProjectOptionsFromScript(filePath, getFileSourceText filePath) + |> Async.RunSynchronously + |> fst + { + Checker = checker + Options = options + } + |> Some + + [] + member _.Run() = + let config = getConfig() + let _, result = + config.Checker.ParseAndCheckFileInProject(filePath, 0, getFileSourceText filePath, config.Options) + |> Async.RunSynchronously + + match result with + | FSharpCheckFileAnswer.Aborted -> failwith "checker aborted" + | FSharpCheckFileAnswer.Succeeded results -> + if results.Diagnostics.Length > 0 then failwithf $"had errors: %A{results.Diagnostics}" + + [] + member _.Cleanup() = + let checker = getConfig().Checker + checker.InvalidateAll() + checker.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients() diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FSharp.Compiler.Benchmarks.fsproj b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FSharp.Compiler.Benchmarks.fsproj index a8c8ff31bc6..55968edddaf 100644 --- a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FSharp.Compiler.Benchmarks.fsproj +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FSharp.Compiler.Benchmarks.fsproj @@ -4,13 +4,6 @@ Exe net8.0 true - - $(NoWarn);NU1505 false @@ -21,18 +14,17 @@ + - - diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FileCascadeBenchmarks.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FileCascadeBenchmarks.fs index 17822adeb96..686153577fa 100644 --- a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FileCascadeBenchmarks.fs +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FileCascadeBenchmarks.fs @@ -68,7 +68,7 @@ let processFunc{number} (x) (func:MyFunctionType{number}) = }} //$COMMENTAREA$""" -/// Code create using FSharpCheckFileResults.GenerateSignature() +/// Code created using FSharpCheckFileResults.GenerateSignature() let generateFsi number = $""" module Benchmark{number} diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/benchmarks.ipynb b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/benchmarks.ipynb deleted file mode 100644 index 5fae6333c77..00000000000 --- a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/benchmarks.ipynb +++ /dev/null @@ -1,117 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "pwsh" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "#!pwsh\n", - "dotnet build -c release\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "fsharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "#r \"../../../artifacts/bin/FSharp.Compiler.Benchmarks/Release/net8.0/FSharp.Compiler.Benchmarks.dll\"\n", - "#r \"../../../artifacts/bin/FSharp.Compiler.Benchmarks/Release/net8.0/BenchmarkDotNet.dll\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "fsharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "open BenchmarkDotNet.Running\n", - "open FSharp.Compiler.Benchmarks\n", - "\n", - "let summary = BenchmarkRunner.Run()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "fsharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "// https://benchmarkdotnet.org/api/BenchmarkDotNet.Reports.BenchmarkReport.html\n", - "#r \"nuget: XPlot.Plotly.Interactive, 4.0.2\"\n", - "\n", - "open XPlot.Plotly\n", - "\n", - "let gcStats = summary.Reports |> Seq.map (fun x -> x.GcStats)\n", - "\n", - "let gen0Series =\n", - " Bar(\n", - " name = \"Gen 0\",\n", - " y = (gcStats |> Seq.map (fun x -> x.Gen0Collections))\n", - " )\n", - "\n", - "let gen1Series =\n", - " Bar(\n", - " name = \"Gen 1\",\n", - " y = (gcStats |> Seq.map (fun x -> x.Gen1Collections))\n", - " )\n", - "\n", - "let gen2Series =\n", - " Bar(\n", - " name = \"Gen 2\",\n", - " y = (gcStats |> Seq.map (fun x -> x.Gen2Collections))\n", - " )\n", - "\n", - "[gen0Series;gen1Series;gen2Series]\n", - "|> Chart.Plot\n", - "|> Chart.WithTitle(\"F# Type-Checking Benchmark 1 - GC Collection Counts\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".NET (C#)", - "language": "C#", - "name": ".net-csharp" - }, - "language_info": { - "file_extension": ".cs", - "mimetype": "text/x-csharp", - "name": "C#", - "pygments_lexer": "csharp", - "version": "9.0" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE100xnest1.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE100xnest1.fs new file mode 100644 index 00000000000..094513ff80c --- /dev/null +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE100xnest1.fs @@ -0,0 +1,115 @@ +module SomeModule = + + type StrChainBuilder() = + member this.Zero() = "" + member this.Delay(f) = f () + member this.Yield(x: string) = x + member this.Combine(a, b) = a + b + + let strchain = StrChainBuilder() + + let test = + // 100 x nesting of 1 + strchain { + "test0" + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + strchain { "test1" } + } diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE100xnest10.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE100xnest10.fs new file mode 100644 index 00000000000..0afe4a1d3f6 --- /dev/null +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE100xnest10.fs @@ -0,0 +1,3616 @@ +module SomeModule = + + type StrChainBuilder() = + member this.Zero() = "" + member this.Delay(f) = f () + member this.Yield(x: string) = x + member this.Combine(a, b) = a + b + + let strchain = StrChainBuilder() + + // 100 x nesting of 10 + let test = + strchain { + "test0" + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { + "test5" + + strchain { + "test6" + + strchain { + "test7" + + strchain { + "test8" + + strchain { + "test9" + strchain { "test10" } + } + } + } + } + } + } + } + } + } + } diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE100xnest5.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE100xnest5.fs new file mode 100644 index 00000000000..28ccd4c1593 --- /dev/null +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE100xnest5.fs @@ -0,0 +1,1615 @@ +module SomeModule = + + type StrChainBuilder() = + member this.Zero() = "" + member this.Delay(f) = f () + member this.Yield(x: string) = x + member this.Combine(a, b) = a + b + + let strchain = StrChainBuilder() + + // 100 x nesting of 5 + let test = + strchain { + "test0" + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + strchain { "test5" } + } + } + } + } + } diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE200xnest5.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE200xnest5.fs new file mode 100644 index 00000000000..0295cec82cf --- /dev/null +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CE200xnest5.fs @@ -0,0 +1,3615 @@ +module SomeModule = + + type StrChainBuilder() = + member this.Zero() = "" + member this.Delay(f) = f () + member this.Yield(x: string) = x + member this.Combine(a, b) = a + b + + let strchain = StrChainBuilder() + + // 200 x nesting of 5 + let test = + strchain { + "test0" + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + + strchain { + "test1" + + strchain { + "test2" + + strchain { + "test3" + + strchain { + "test4" + + strchain { "test5" } + } + } + } + } + } diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CEwCO100xnest5.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CEwCO100xnest5.fs new file mode 100644 index 00000000000..d196ed0d91a --- /dev/null +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CEwCO100xnest5.fs @@ -0,0 +1,2937 @@ +module CalculationCE = + + type CalcState = { r: int } + + type CalculationBuilder() = + member _.Yield _ = { r = 0 } + member _.Return(x: int) = { r = x } + member _.ReturnFrom(x) = x + + [] + member _.Add(state: CalcState, x) = { r = state.r + x } + + [] + member _.Sub(state: CalcState, x) = { r = state.r - x } + + [] + member _.Mul(state: CalcState, x) = { r = state.r * x } + + [] + member _.Div(state: CalcState, x) = + if x = 0 then + failwith "can't divide by 0" + + { r = state.r / x } + + let calculation = CalculationBuilder() + +open CalculationCE + +// 100 x nesting of 5 +let c = + calculation { + + let c1 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c2 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c3 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c4 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c5 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c6 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c7 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c8 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c9 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c10 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c11 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c12 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c13 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c14 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c15 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c16 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c17 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c18 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c19 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c20 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c21 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c22 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c23 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c24 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c25 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c26 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c27 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c28 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c29 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c30 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c31 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c32 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c33 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c34 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c35 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c36 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c37 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c38 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c39 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c40 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c41 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c42 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c43 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c44 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c45 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c46 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c47 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c48 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c49 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c50 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c51 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c52 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c53 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c54 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c55 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c56 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c57 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c58 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c59 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c60 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c61 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c62 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c63 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c64 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c65 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c66 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c67 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c68 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c69 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c70 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c71 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c72 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c73 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c74 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c75 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c76 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c77 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c78 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c79 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c80 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c81 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c82 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c83 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c84 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c85 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c86 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c87 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c88 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c89 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c90 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c91 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c92 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c93 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c94 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c95 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c96 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c97 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c98 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c99 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let c100 = + calculation { + let nest2 = + calculation { + let nest3 = + calculation { + let nest4 = + calculation { + let nest5 = + calculation { + add 1 + sub 1 + mul 1 + div 1 + } + + return! nest5 + } + + return! nest4 + } + + return! nest3 + } + + return! nest2 + } + + let s = + [ c1.r + c2.r + c3.r + c4.r + c5.r + c6.r + c7.r + c8.r + c9.r + c10.r + c11.r + c12.r + c13.r + c14.r + c15.r + c16.r + c17.r + c18.r + c19.r + c20.r + c21.r + c22.r + c23.r + c24.r + c25.r + c26.r + c27.r + c28.r + c29.r + c30.r + c31.r + c32.r + c33.r + c34.r + c35.r + c36.r + c37.r + c38.r + c39.r + c40.r + c41.r + c42.r + c43.r + c44.r + c45.r + c46.r + c47.r + c48.r + c49.r + c50.r + c51.r + c52.r + c53.r + c54.r + c55.r + c56.r + c57.r + c58.r + c59.r + c60.r + c61.r + c62.r + c63.r + c64.r + c65.r + c66.r + c67.r + c68.r + c69.r + c70.r + c71.r + c72.r + c73.r + c74.r + c75.r + c76.r + c77.r + c78.r + c79.r + c80.r + c81.r + c82.r + c83.r + c84.r + c85.r + c86.r + c87.r + c88.r + c89.r + c90.r + c91.r + c92.r + c93.r + c94.r + c95.r + c96.r + c97.r + c98.r + c99.r + c100.r ] + + return! s |> List.sum + } diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CEwCO500xnest1.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CEwCO500xnest1.fs new file mode 100644 index 00000000000..c67f8e73528 --- /dev/null +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/ce/CEwCO500xnest1.fs @@ -0,0 +1,539 @@ +module CalculationCE = + + type CalcState = + { r: int } + + type CalculationBuilder() = + member _.Yield _ = + { r = 0 } + + [] + member _.Add(state: CalcState, x) = + { state with + r = state.r + x } + + [] + member _.Sub(state: CalcState, x) = + { state with + r = state.r - x } + + [] + member _.Mul(state: CalcState, x) = + { state with + r = state.r * x } + + [] + member _.Div(state: CalcState, x) = + if x = 0 then + failwith "can't divide by 0" + { state with + r = state.r / x } + + let calculation = CalculationBuilder() + +open CalculationCE + +let c = + // 500 applications of custom operations + calculation { + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + add 1 + sub 1 + mul 1 + div 1 + } diff --git a/tests/benchmarks/FCSBenchmarks/FCSSourceFiles/FCSSourceFiles.fsproj b/tests/benchmarks/FCSBenchmarks/FCSSourceFiles/FCSSourceFiles.fsproj index 5f0d38af2ef..3774aa87023 100644 --- a/tests/benchmarks/FCSBenchmarks/FCSSourceFiles/FCSSourceFiles.fsproj +++ b/tests/benchmarks/FCSBenchmarks/FCSSourceFiles/FCSSourceFiles.fsproj @@ -3,6 +3,7 @@ Exe net8.0 + true diff --git a/tests/benchmarks/FCSBenchmarks/FCSSourceFiles/Program.fs b/tests/benchmarks/FCSBenchmarks/FCSSourceFiles/Program.fs index 136897e081b..9c8148ed4da 100644 --- a/tests/benchmarks/FCSBenchmarks/FCSSourceFiles/Program.fs +++ b/tests/benchmarks/FCSBenchmarks/FCSSourceFiles/Program.fs @@ -270,7 +270,7 @@ module Project = OriginalLoadReferences = [] Stamp = None } - FSharpReferencedProject.CreateFSharp( + FSharpReferencedProject.FSharpReference( __SOURCE_DIRECTORY__ + @"\..\..\..\..\artifacts\bin\FSharp.Core\Debug\netstandard2.1\FSharp.Core.dll", projectOptions ) @@ -459,7 +459,7 @@ module Project = OriginalLoadReferences = [] Stamp = None } - FSharpReferencedProject.CreateFSharp( + FSharpReferencedProject.FSharpReference( __SOURCE_DIRECTORY__ + @"\..\..\..\..\artifacts\bin\FSharp.DependencyManager.Nuget\Debug\netstandard2.0\FSharp.DependencyManager.Nuget.dll", projectOptions ) @@ -890,8 +890,7 @@ type CompilerService() = | None -> sourceOpt <- projectOptions.SourceFiles - |> Array.filter (fun filePath -> filePath.EndsWith("CheckDeclarations.fs")) // || filePath.EndsWith("CheckExpressions.fs")) - // || filePath.EndsWith("lex.fs") || filePath.EndsWith("pars.fs")) + |> Array.filter (fun filePath -> filePath.EndsWith("CheckDeclarations.fs")) |> Array.map (fun filePath -> filePath, SourceText.ofString (File.ReadAllText(filePath))) |> Some | _ -> () diff --git a/tests/benchmarks/Fsharp.ProfilingStartpointProject/Fsharp.ProfilingStartpointProject.fsproj b/tests/benchmarks/Fsharp.ProfilingStartpointProject/Fsharp.ProfilingStartpointProject.fsproj deleted file mode 100644 index 6cb9e4bd78c..00000000000 --- a/tests/benchmarks/Fsharp.ProfilingStartpointProject/Fsharp.ProfilingStartpointProject.fsproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - Exe - net8.0 - - - - - - - - - - - diff --git a/tests/benchmarks/Fsharp.ProfilingStartpointProject/Program.fs b/tests/benchmarks/Fsharp.ProfilingStartpointProject/Program.fs deleted file mode 100644 index 5d851e60865..00000000000 --- a/tests/benchmarks/Fsharp.ProfilingStartpointProject/Program.fs +++ /dev/null @@ -1,47 +0,0 @@ -open FSharp.Compiler.Benchmarks - -open System -open System.IO -open System.Text -open FSharp.Compiler.CodeAnalysis -open FSharp.Compiler.Diagnostics -open FSharp.Compiler.EditorServices -open FSharp.Compiler.Text -open FSharp.Compiler.AbstractIL.IL -open FSharp.Compiler.AbstractIL.ILBinaryReader -open BenchmarkDotNet.Attributes -open FSharp.Compiler.Benchmarks -open Microsoft.CodeAnalysis.Text -open BenchmarkDotNet.Order -open BenchmarkDotNet.Mathematics - -let bench = new FileCascadeBenchmarks() -bench.GenerateFSI <- true -do bench.Setup() - -(* -This project was created as an easy entry point for low-level profiling of FCS operations. -The only purpose is the easy of setup (simply set as startup project and launch) so that a profiler can be connected. -There is definitely no harm in deleting it if it starts bothering anyone. -*) - - -[] -let main args = - - match args |> Array.toList with - | ["no-change"] -> - for i=1 to 256 do - printfn "***************************" - printfn "ITERATION %i" i - printfn "***************************" - bench.ParseAndCheckLastFileProjectAsIs() |> ignore - | ["mid-change"] -> - for i=1 to 16 do - printfn "***************************" - printfn "ITERATION %i" i - printfn "***************************" - bench.ParseProjectWithChangingMiddleFile() |> ignore - | _ -> failwith "Invalid args. Use cache-clear or mid-change" - |> ignore - 0 diff --git a/tests/fsharp/Compiler/Libraries/Core/Operators/AbsTests.fs b/tests/fsharp/Compiler/Libraries/Core/Operators/AbsTests.fs index ca2f753de4e..a6e07ba38e4 100644 --- a/tests/fsharp/Compiler/Libraries/Core/Operators/AbsTests.fs +++ b/tests/fsharp/Compiler/Libraries/Core/Operators/AbsTests.fs @@ -29,7 +29,7 @@ abs -1uy |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'byte' does not support the operator 'Abs'" + "The type 'byte' does not support the operator 'abs'" [] let ``Abs of uint16``() = @@ -40,7 +40,7 @@ abs -1us |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'uint16' does not support the operator 'Abs'" + "The type 'uint16' does not support the operator 'abs'" [] let ``Abs of uint32``() = @@ -51,7 +51,7 @@ abs -1ul |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'uint32' does not support the operator 'Abs'" + "The type 'uint32' does not support the operator 'abs'" CompilerAssert.TypeCheckSingleError """ @@ -60,7 +60,7 @@ abs -1u |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 8) - "The type 'uint32' does not support the operator 'Abs'" + "The type 'uint32' does not support the operator 'abs'" [] let ``Abs of unativeint``() = @@ -71,7 +71,7 @@ abs -1un |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'unativeint' does not support the operator 'Abs'" + "The type 'unativeint' does not support the operator 'abs'" [] let ``Abs of uint64``() = @@ -82,7 +82,7 @@ abs -1uL |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'uint64' does not support the operator 'Abs'" + "The type 'uint64' does not support the operator 'abs'" CompilerAssert.TypeCheckSingleError """ @@ -91,4 +91,4 @@ abs -1UL |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'uint64' does not support the operator 'Abs'" \ No newline at end of file + "The type 'uint64' does not support the operator 'abs'" \ No newline at end of file diff --git a/tests/fsharp/Compiler/Libraries/Core/Operators/SignTests.fs b/tests/fsharp/Compiler/Libraries/Core/Operators/SignTests.fs index 2c67b1d1b8d..ca3edf8b377 100644 --- a/tests/fsharp/Compiler/Libraries/Core/Operators/SignTests.fs +++ b/tests/fsharp/Compiler/Libraries/Core/Operators/SignTests.fs @@ -45,7 +45,7 @@ sign 0uy |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'byte' does not support the operator 'get_Sign'" + "The type 'byte' does not support the operator 'sign'" [] let ``Sign of uint16``() = @@ -56,7 +56,7 @@ sign 0us |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'uint16' does not support the operator 'get_Sign'" + "The type 'uint16' does not support the operator 'sign'" [] let ``Sign of uint32``() = @@ -67,7 +67,7 @@ sign 0u |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 8) - "The type 'uint32' does not support the operator 'get_Sign'" + "The type 'uint32' does not support the operator 'sign'" [] let ``Sign of uint64``() = @@ -78,4 +78,4 @@ sign 0uL |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'uint64' does not support the operator 'get_Sign'" \ No newline at end of file + "The type 'uint64' does not support the operator 'sign'" \ No newline at end of file diff --git a/tests/fsharp/typecheck/sigs/neg06.bsl b/tests/fsharp/typecheck/sigs/neg06.bsl index 0443bd5c4a9..d55e3e948d2 100644 --- a/tests/fsharp/typecheck/sigs/neg06.bsl +++ b/tests/fsharp/typecheck/sigs/neg06.bsl @@ -64,27 +64,27 @@ neg06.fs(128,53,128,61): typecheck error FS0043: A type parameter is missing a c neg06.fs(141,10,141,18): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation -neg06.fs(148,13,148,21): typecheck error FS0039: The value or constructor 'BadType1' is not defined. +neg06.fs(148,13,148,21): typecheck error FS0800: Invalid use of a type name neg06.fs(150,10,150,18): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation -neg06.fs(157,13,157,21): typecheck error FS0039: The value or constructor 'BadType2' is not defined. +neg06.fs(157,13,157,21): typecheck error FS0800: Invalid use of a type name neg06.fs(159,10,159,18): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation -neg06.fs(166,13,166,21): typecheck error FS0039: The value or constructor 'BadType3' is not defined. +neg06.fs(166,13,166,21): typecheck error FS0800: Invalid use of a type name neg06.fs(195,10,195,18): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation -neg06.fs(203,13,203,21): typecheck error FS0039: The value or constructor 'BadType1' is not defined. +neg06.fs(203,13,203,21): typecheck error FS0800: Invalid use of a type name neg06.fs(205,10,205,18): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation -neg06.fs(213,13,213,21): typecheck error FS0039: The value or constructor 'BadType2' is not defined. +neg06.fs(213,13,213,21): typecheck error FS0800: Invalid use of a type name neg06.fs(215,10,215,18): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation -neg06.fs(223,13,223,21): typecheck error FS0039: The value or constructor 'BadType3' is not defined. +neg06.fs(223,13,223,21): typecheck error FS0800: Invalid use of a type name neg06.fs(300,10,300,12): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'. @@ -100,11 +100,11 @@ neg06.fs(320,10,320,12): typecheck error FS0937: Only structs and classes withou neg06.fs(326,10,326,18): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation -neg06.fs(335,13,335,21): typecheck error FS0039: The value or constructor 'BadType4' is not defined. +neg06.fs(335,13,335,21): typecheck error FS0800: Invalid use of a type name neg06.fs(340,10,340,18): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation -neg06.fs(350,13,350,21): typecheck error FS0039: The value or constructor 'BadType4' is not defined. +neg06.fs(350,13,350,21): typecheck error FS0800: Invalid use of a type name neg06.fs(375,9,375,10): typecheck error FS1197: The parameter 'x' was inferred to have byref type. Parameters of byref type must be given an explicit type annotation, e.g. 'x1: byref'. When used, a byref parameter is implicitly dereferenced. diff --git a/tests/fsharp/typecheck/sigs/neg61.bsl b/tests/fsharp/typecheck/sigs/neg61.bsl index b1ba15a77ad..e0b2fb5eafb 100644 --- a/tests/fsharp/typecheck/sigs/neg61.bsl +++ b/tests/fsharp/typecheck/sigs/neg61.bsl @@ -71,7 +71,7 @@ neg61.fs(111,13,111,24): typecheck error FS3144: 'return' and 'return!' may not neg61.fs(114,13,114,21): typecheck error FS3145: This is not a known query operator. Query operators are identifiers such as 'select', 'where', 'sortBy', 'thenBy', 'groupBy', 'groupValBy', 'join', 'groupJoin', 'sumBy' and 'averageBy', defined using corresponding methods on the 'QueryBuilder' type. -neg61.fs(114,22,114,23): typecheck error FS0001: The type 'int' does not support the operator 'Truncate' +neg61.fs(114,22,114,23): typecheck error FS0001: The type 'int' does not support the operator 'truncate' neg61.fs(133,17,133,20): typecheck error FS3147: This 'let' definition may not be used in a query. Only simple value definitions may be used in queries. diff --git a/tests/fsharpqa/Source/Conformance/Expressions/ExpressionQuotations/Baselines/E_Cast.fs b/tests/fsharpqa/Source/Conformance/Expressions/ExpressionQuotations/Baselines/E_Cast.fs index fdfeed0171e..bd3772bf30c 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/ExpressionQuotations/Baselines/E_Cast.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/ExpressionQuotations/Baselines/E_Cast.fs @@ -1,7 +1,6 @@ // #Regression #Conformance #Quotations // Verify type annotation is required for casting quotes -//Value restriction\. The value 'tq' has been inferred to have generic type. val tq: Expr<'_a> .Either define 'tq' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation\.$ -// +//Value restriction: The value 'tq' has an inferred generic type val tq: Expr<'_a>However, values cannot have generic type variables like '_a in "let x: '_a"\. You can do one of the following:- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"- Add an explicit type annotation like "let x : int"- Use the value as a non-generic type in later code for type inference like "do x"or if you still want type-dependent results, you can define 'tq' as a function instead by doing either:- Add a unit parameter like "let x\(\)"- Write explicit type parameters like "let x<'a>".This error is because a let binding without parameters defines a value, not a function\. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results\.$ open Microsoft.FSharp.Quotations diff --git a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/E_ValueRestriction01.fs b/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/E_ValueRestriction01.fs index d66cc047dc4..cf485b37d8c 100644 --- a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/E_ValueRestriction01.fs +++ b/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/E_ValueRestriction01.fs @@ -3,13 +3,16 @@ // Verify error associated with open type variable -(* -error FS0030: Value restriction. The value 'x' has been inferred to have generic type - val x : '_a list ref -Either define 'x' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type constraint. -*) -//Value restriction. The value - +//Value restriction: The value 'x' has an inferred generic type +// val x: '_a list ref +//However, values cannot have generic type variables like '_a in "let x: '_a"\. You can do one of the following: +//- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1" +//- Add an explicit type annotation like "let x : int" +//- Use the value as a non-generic type in later code for type inference like "do x" +//or if you still want type-dependent results, you can define 'x' as a function instead by doing either: +//- Add a unit parameter like "let x()" +//- Write explicit type parameters like "let x<'a>"\. +//This error is because a let binding without parameters defines a value, not a function\. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results\.$ let x = ref [] exit 1 diff --git a/tests/fsharpqa/Source/Conformance/InferenceProcedures/DispatchSlotInference/E_GenInterfaceWGenMethods01.fs b/tests/fsharpqa/Source/Conformance/InferenceProcedures/DispatchSlotInference/E_GenInterfaceWGenMethods01.fs index 5d87e71957e..8a65831546e 100644 --- a/tests/fsharpqa/Source/Conformance/InferenceProcedures/DispatchSlotInference/E_GenInterfaceWGenMethods01.fs +++ b/tests/fsharpqa/Source/Conformance/InferenceProcedures/DispatchSlotInference/E_GenInterfaceWGenMethods01.fs @@ -1,7 +1,7 @@ // #Regression #Conformance #TypeInference // FSHARP1.0:1445. See also FSHARP1.0:4721 // Failure when generating code for generic interface with generic method -//Value restriction\. The value 'result' has been inferred to have generic type. val result: '_a array when '_a: equality and '_a: null .Either define 'result' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation\.$ +//Value restriction: The value 'result' has an inferred generic type val result: '_a array when '_a: equality and '_a: nullHowever, values cannot have generic type variables like '_a in "let x: '_a"\. You can do one of the following:- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"- Add an explicit type annotation like "let x : int"- Use the value as a non-generic type in later code for type inference like "do x"or if you still want type-dependent results, you can define 'result' as a function instead by doing either:- Add a unit parameter like "let x\(\)"- Write explicit type parameters like "let x<'a>".This error is because a let binding without parameters defines a value, not a function\. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results\.$ type 'a IFoo = interface abstract DoStuff<'b> : 'a -> 'b array end diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/ValueRestriction/E_NotMemberOrFunction01.fsx b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/ValueRestriction/E_NotMemberOrFunction01.fsx index 182fb04be48..a33da54e3f9 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/ValueRestriction/E_NotMemberOrFunction01.fsx +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/ValueRestriction/E_NotMemberOrFunction01.fsx @@ -1,6 +1,6 @@ // #Conformance #ObjectOrientedTypes #Classes #TypeInference #ValueRestriction -//Value restriction\. The value 'x1' has been inferred to have generic type. val x1: \('_a -> unit\) .Either make the arguments to 'x1' explicit or, if you do not intend for it to be generic, add a type annotation\.$ +//Value restriction: The value 'x1' has an inferred generic function type val x1: \('_a -> unit\)However, values cannot have generic type variables like '_a in "let f: '_a". You should define 'x1' as a function instead by doing one of the following:- Add an explicit parameter that is applied instead of using a partial application "let f param"- Add a unit parameter like "let f\(\)"- Write explicit type parameters like "let f<'a>"or if you do not intend for it to be generic, either:- Add an explicit type annotation like "let f : obj -> obj"- Apply arguments of non-generic types to the function value in later code for type inference like "do f\(\)"\.This error is because a let binding without parameters defines a value, not a function\. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results\.$ // We expect a value restriction here. The inferred signature is: // val x1: (?1 -> unit) @@ -8,4 +8,4 @@ // variable could have feasibly be genrealized at 'x1' (c.f. the case above, where it // was generalized). let f1 (x:obj) = () -let x1 = ((); f1) \ No newline at end of file +let x1 = ((); f1) diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs index b4e05661698..dca7226146d 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs @@ -1,6 +1,5 @@ // #Regression #Conformance #ObjectOrientedTypes #Enums -//Enumerations cannot have members$ -//The type 'Season' does not support the operator 'get_One'$ +//Enumerations cannot have members$ type Season = Spring=0 | Summer=1 | Autumn=2 | Winter=3 with @@ -8,5 +7,3 @@ type Season = Spring=0 | Summer=1 | Autumn=2 | Winter=3 let starti = Enum.to_int start let stopi = Enum.to_int stop { for i in starti .. stopi -> Enum.of_int i } - -printfn "%A" [Season.Spring .. Season.Autumn] diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_InvalidRecursiveGeneric01.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_InvalidRecursiveGeneric01.fs index 2d426f6244f..9324d3e4902 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_InvalidRecursiveGeneric01.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_InvalidRecursiveGeneric01.fs @@ -3,7 +3,7 @@ // Regression for FSB 3417 //This type definition involves an immediate cyclic reference through a struct field or inheritance relation -//The value or constructor 'BadType4' is not defined +//Invalid use of a type name type BadType4 = struct diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_InvalidRecursiveGeneric02.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_InvalidRecursiveGeneric02.fs index 21854ced87a..f90ab777f41 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_InvalidRecursiveGeneric02.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_InvalidRecursiveGeneric02.fs @@ -3,7 +3,7 @@ // Regression for FSB 3417 //This type definition involves an immediate cyclic reference through a struct field or inheritance relation -//The value or constructor 'BadType4' is not defined +//Invalid use of a type name type BadType4 = struct diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_StructConstruction03.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_StructConstruction03.fs index de295146093..0ee07b3415e 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_StructConstruction03.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_StructConstruction03.fs @@ -2,8 +2,8 @@ // Regression test for FSHARP1.0:3143 //This type definition involves an immediate cyclic reference through a struct field or inheritance relation$ //This declaration element is not permitted in an augmentation$ -//The value or constructor 'S' is not defined -//The value or constructor 'S' is not defined +//Invalid use of a type name +//Invalid use of a type name type S(x:S) = struct end diff --git a/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/Diagnostics/W_NonGenVarInValueRestrictionWarning.fs b/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/Diagnostics/W_NonGenVarInValueRestrictionWarning.fs index 12ca2be2ce8..6552aa57379 100644 --- a/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/Diagnostics/W_NonGenVarInValueRestrictionWarning.fs +++ b/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/Diagnostics/W_NonGenVarInValueRestrictionWarning.fs @@ -1,7 +1,7 @@ // #Regression #Conformance #UnitsOfMeasure #Diagnostics // Regression test for FSHARP1.0:4969 // Non-generalized unit-of-measure variables should display with "_" in value restriction warning -//.+val x: float<'_u> list ref -//.+val y: '_a list ref +//Value restriction: The value 'x' has an inferred generic type val x: float<'_u> list refHowever, values cannot have generic type variables like '_a in "let x: '_a"\. You can do one of the following:- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"- Add an explicit type annotation like "let x : int"- Use the value as a non-generic type in later code for type inference like "do x"or if you still want type-dependent results, you can define 'x' as a function instead by doing either:- Add a unit parameter like "let x\(\)"- Write explicit type parameters like "let x<'a>".This error is because a let binding without parameters defines a value, not a function\. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results\. +//Value restriction: The value 'y' has an inferred generic type val y: '_a list refHowever, values cannot have generic type variables like '_a in "let x: '_a"\. You can do one of the following:- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"- Add an explicit type annotation like "let x : int"- Use the value as a non-generic type in later code for type inference like "do x"or if you still want type-dependent results, you can define 'y' as a function instead by doing either:- Add a unit parameter like "let x\(\)"- Write explicit type parameters like "let x<'a>".This error is because a let binding without parameters defines a value, not a function\. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results\.$ let x = ref ([] : float<_> list) let y = ref ([] : _ list) diff --git a/tests/fsharpqa/Source/Diagnostics/NONTERM/tuplewithlazy01.fs b/tests/fsharpqa/Source/Diagnostics/NONTERM/tuplewithlazy01.fs index 8e2724f49ce..cfbd4185bd4 100644 --- a/tests/fsharpqa/Source/Diagnostics/NONTERM/tuplewithlazy01.fs +++ b/tests/fsharpqa/Source/Diagnostics/NONTERM/tuplewithlazy01.fs @@ -1,8 +1,8 @@ // #Regression #Diagnostics // Regression test for DevDiv:64339 // Note that the bug still repros in CHK/DBG bits - we will knownfail it -//Unexpected keyword 'lazy' in type definition$ -//Unexpected keyword 'lazy'$ +//Unexpected keyword 'lazy' in pattern$ +//Unexpected keyword 'lazy' in pattern$ // 5 elements -> ok type Ok(a, b, c, d, e : lazy) = class end diff --git a/tests/fsharpqa/Source/Diagnostics/NONTERM/tuplewithlazy01b.fs b/tests/fsharpqa/Source/Diagnostics/NONTERM/tuplewithlazy01b.fs index 8e2724f49ce..cfbd4185bd4 100644 --- a/tests/fsharpqa/Source/Diagnostics/NONTERM/tuplewithlazy01b.fs +++ b/tests/fsharpqa/Source/Diagnostics/NONTERM/tuplewithlazy01b.fs @@ -1,8 +1,8 @@ // #Regression #Diagnostics // Regression test for DevDiv:64339 // Note that the bug still repros in CHK/DBG bits - we will knownfail it -//Unexpected keyword 'lazy' in type definition$ -//Unexpected keyword 'lazy'$ +//Unexpected keyword 'lazy' in pattern$ +//Unexpected keyword 'lazy' in pattern$ // 5 elements -> ok type Ok(a, b, c, d, e : lazy) = class end diff --git a/tests/projects/Sample_Local_Compiler_and_FSLib/LocalCompilerAndFslib.fsproj b/tests/projects/Sample_Local_Compiler_and_FSLib/LocalCompilerAndFslib.fsproj new file mode 100644 index 00000000000..c2164b65666 --- /dev/null +++ b/tests/projects/Sample_Local_Compiler_and_FSLib/LocalCompilerAndFslib.fsproj @@ -0,0 +1,23 @@ + + + + Exe + net8.0 + preview + true + + + + true + $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Debug/net8.0/fsc.dll + $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Debug/net8.0/fsc.dll + False + True + + + + + + + + diff --git a/tests/projects/Sample_Local_Compiler_and_FSLib/Program.fs b/tests/projects/Sample_Local_Compiler_and_FSLib/Program.fs new file mode 100644 index 00000000000..1ffa8063569 --- /dev/null +++ b/tests/projects/Sample_Local_Compiler_and_FSLib/Program.fs @@ -0,0 +1,25 @@ +module Program + +type CBuilder() = + [] + member this.Foo _ = "Foo" + [] + member this.foo _ = "foo" + member this.Yield _ = () + member this.Zero _ = () + + +[] +let main _ = + let cb = CBuilder() + + let x = cb { Foo } + let y = cb { foo } + printfn $"{x}" + printfn $"{y}" + + if x <> "Foo" then + failwith "not Foo" + if y <> "foo" then + failwith "not foo" + 0 diff --git a/tests/projects/misc/SelfDefinedTailCallAttribute/Attribute.fs b/tests/projects/misc/SelfDefinedTailCallAttribute/Attribute.fs new file mode 100644 index 00000000000..afa7331896d --- /dev/null +++ b/tests/projects/misc/SelfDefinedTailCallAttribute/Attribute.fs @@ -0,0 +1,6 @@ +module Microsoft.FSharp.Core + + open System + + [] + type TailCallAttribute() = inherit Attribute() diff --git a/tests/projects/misc/SelfDefinedTailCallAttribute/Program.fs b/tests/projects/misc/SelfDefinedTailCallAttribute/Program.fs new file mode 100644 index 00000000000..7652c7c2ecb --- /dev/null +++ b/tests/projects/misc/SelfDefinedTailCallAttribute/Program.fs @@ -0,0 +1,13 @@ +namespace N + + module M = + + open Microsoft.FSharp.Core + + [] + let rec f x = 1 + f x + + [] + let main argv = + printfn "Hello from F#" + 0 diff --git a/tests/projects/misc/SelfDefinedTailCallAttribute/tailcallaltattr.fsproj b/tests/projects/misc/SelfDefinedTailCallAttribute/tailcallaltattr.fsproj new file mode 100644 index 00000000000..92c5ae861d4 --- /dev/null +++ b/tests/projects/misc/SelfDefinedTailCallAttribute/tailcallaltattr.fsproj @@ -0,0 +1,20 @@ + + + Exe + net6.0 + true + preview + + + + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Debug/net8.0/fsc.dll + + + + + + + + + + \ No newline at end of file diff --git a/tests/service/Common.fs b/tests/service/Common.fs index a8d4782de0d..8516948626a 100644 --- a/tests/service/Common.fs +++ b/tests/service/Common.fs @@ -31,7 +31,7 @@ type Async with task.Result // Create one global interactive checker instance -let checker = FSharpChecker.Create() +let checker = FSharpChecker.Create(useTransparentCompiler=FSharp.Compiler.CompilerConfig.FSharpExperimentalFeaturesEnabledAutomatically) type TempFile(ext, contents: string) = let tmpFile = Path.ChangeExtension(tryCreateTemporaryFileName (), ext) @@ -137,8 +137,8 @@ let mkTestFileAndOptions source additionalArgs = let fileSource1 = "module M" FileSystem.OpenFileForWriteShim(fileName).Write(fileSource1) - let args = Array.append (mkProjectCommandLineArgs (dllName, [fileName])) additionalArgs - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let args = Array.append (mkProjectCommandLineArgs (dllName, [])) additionalArgs + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = [| fileName |] } fileName, options let parseAndCheckFile fileName source options = @@ -158,7 +158,7 @@ let parseAndCheckScriptWithOptions (file:string, input, opts) = let fname = Path.Combine(path, Path.GetFileName(file)) let dllName = Path.ChangeExtension(fname, ".dll") let projName = Path.ChangeExtension(fname, ".fsproj") - let args = mkProjectCommandLineArgsForScript (dllName, [file]) + let args = mkProjectCommandLineArgsForScript (dllName, []) printfn "file = %A, args = %A" file args checker.GetProjectOptionsFromCommandLineArgs (projName, args) @@ -171,7 +171,7 @@ let parseAndCheckScriptWithOptions (file:string, input, opts) = //printfn "projectOptions = %A" projectOptions #endif - let projectOptions = { projectOptions with OtherOptions = Array.append opts projectOptions.OtherOptions } + let projectOptions = { projectOptions with OtherOptions = Array.append opts projectOptions.OtherOptions; SourceFiles = [|file|] } let parseResult, typedRes = checker.ParseAndCheckFileInProject(file, 0, SourceText.ofString input, projectOptions) |> Async.RunImmediate // if parseResult.Errors.Length > 0 then diff --git a/tests/service/ExprTests.fs b/tests/service/ExprTests.fs index 662a60edc80..7b35568e38d 100644 --- a/tests/service/ExprTests.fs +++ b/tests/service/ExprTests.fs @@ -364,8 +364,8 @@ let createOptionsAux fileSources extraArgs = Utils.createTempDir() for fileSource: string, fileName in List.zip fileSources fileNames do FileSystem.OpenFileForWriteShim(fileName).Write(fileSource) - let args = [| yield! extraArgs; yield! mkProjectCommandLineArgs (dllName, fileNames) |] - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let args = [| yield! extraArgs; yield! mkProjectCommandLineArgs (dllName, []) |] + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames |> List.toArray } Utils.cleanupTempFiles (fileNames @ [dllName; projFileName]), options @@ -732,11 +732,13 @@ let ignoreTestIfStackOverflowExpected () = #endif /// This test is run in unison with its optimized counterpart below +[] +[] [] -let ``Test Unoptimized Declarations Project1`` () = +let ``Test Unoptimized Declarations Project1`` useTransparentCompiler = let cleanup, options = Project1.createOptionsWithArgs [ "--langversion:preview" ] use _holder = cleanup - let exprChecker = FSharpChecker.Create(keepAssemblyContents=true) + let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate for e in wholeProjectResults.Diagnostics do @@ -871,11 +873,13 @@ let ``Test Unoptimized Declarations Project1`` () = () +[] +[] [] -let ``Test Optimized Declarations Project1`` () = +let ``Test Optimized Declarations Project1`` useTransparentCompiler = let cleanup, options = Project1.createOptionsWithArgs [ "--langversion:preview" ] use _holder = cleanup - let exprChecker = FSharpChecker.Create(keepAssemblyContents=true) + let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate for e in wholeProjectResults.Diagnostics do @@ -1017,7 +1021,7 @@ let testOperators dnName fsName excludedTests expectedUnoptimized expectedOptimi let filePath = Utils.getTempFilePathChangeExt tempFileName ".fs" let dllPath =Utils.getTempFilePathChangeExt tempFileName ".dll" let projFilePath = Utils.getTempFilePathChangeExt tempFileName ".fsproj" - let exprChecker = FSharpChecker.Create(keepAssemblyContents=true) + let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=true) begin use _cleanup = Utils.cleanupTempFiles [filePath; dllPath; projFilePath] @@ -1027,9 +1031,9 @@ let testOperators dnName fsName excludedTests expectedUnoptimized expectedOptimi let fileSource = excludedTests |> List.fold replace source FileSystem.OpenFileForWriteShim(filePath).Write(fileSource) - let args = mkProjectCommandLineArgsSilent (dllPath, [filePath]) + let args = mkProjectCommandLineArgsSilent (dllPath, []) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFilePath, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFilePath, args) with SourceFiles = [|filePath|] } let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate let referencedAssemblies = wholeProjectResults.ProjectContext.GetReferencedAssemblies() @@ -3206,12 +3210,14 @@ let BigSequenceExpression(outFileOpt,docFileOpt,baseAddressOpt) = let createOptions() = createOptionsAux [fileSource1] [] +[] +[] [] -let ``Test expressions of declarations stress big expressions`` () = +let ``Test expressions of declarations stress big expressions`` useTransparentCompiler = ignoreTestIfStackOverflowExpected () let cleanup, options = ProjectStressBigExpressions.createOptions() use _holder = cleanup - let exprChecker = FSharpChecker.Create(keepAssemblyContents=true) + let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate wholeProjectResults.Diagnostics.Length |> shouldEqual 0 @@ -3223,12 +3229,14 @@ let ``Test expressions of declarations stress big expressions`` () = printDeclarations None (List.ofSeq file1.Declarations) |> Seq.toList |> ignore +[] +[] [] -let ``Test expressions of optimized declarations stress big expressions`` () = +let ``Test expressions of optimized declarations stress big expressions`` useTransparentCompiler = ignoreTestIfStackOverflowExpected () let cleanup, options = ProjectStressBigExpressions.createOptions() use _holder = cleanup - let exprChecker = FSharpChecker.Create(keepAssemblyContents=true) + let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate wholeProjectResults.Diagnostics.Length |> shouldEqual 0 @@ -3284,11 +3292,13 @@ let f8() = callXY (D()) (C()) let createOptions() = createOptionsAux [fileSource1] ["--langversion:7.0"] +[] +[] [] -let ``Test ProjectForWitnesses1`` () = +let ``Test ProjectForWitnesses1`` useTransparentCompiler = let cleanup, options = ProjectForWitnesses1.createOptions() use _holder = cleanup - let exprChecker = FSharpChecker.Create(keepAssemblyContents=true) + let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate for e in wholeProjectResults.Diagnostics do @@ -3328,11 +3338,13 @@ let ``Test ProjectForWitnesses1`` () = |> shouldPairwiseEqual expected +[] +[] [] -let ``Test ProjectForWitnesses1 GetWitnessPassingInfo`` () = +let ``Test ProjectForWitnesses1 GetWitnessPassingInfo`` useTransparentCompiler = let cleanup, options = ProjectForWitnesses1.createOptions() use _holder = cleanup - let exprChecker = FSharpChecker.Create(keepAssemblyContents=true) + let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate for e in wholeProjectResults.Diagnostics do @@ -3408,11 +3420,13 @@ type MyNumberWrapper = let createOptions() = createOptionsAux [fileSource1] ["--langversion:7.0"] +[] +[] [] -let ``Test ProjectForWitnesses2`` () = +let ``Test ProjectForWitnesses2`` useTransparentCompiler = let cleanup, options = ProjectForWitnesses2.createOptions() use _holder = cleanup - let exprChecker = FSharpChecker.Create(keepAssemblyContents=true) + let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate for e in wholeProjectResults.Diagnostics do @@ -3428,7 +3442,6 @@ let ``Test ProjectForWitnesses2`` () = "member Neg(p) = {x = Operators.op_UnaryNegation (fun arg0_0 -> LanguagePrimitives.UnaryNegationDynamic (arg0_0),p.x); y = Operators.op_UnaryNegation (fun arg0_0 -> LanguagePrimitives.UnaryNegationDynamic (arg0_0),p.y)} @ (7,34--7,56)"; "member op_Addition(p1,p2) = {x = Operators.op_Addition (fun arg0_0 -> fun arg1_0 -> LanguagePrimitives.AdditionDynamic (arg0_0,arg1_0),p1.x,p2.x); y = Operators.op_Addition (fun arg0_0 -> fun arg1_0 -> LanguagePrimitives.AdditionDynamic (arg0_0,arg1_0),p1.y,p2.y)} @ (8,33--8,68)"; "type MyNumber"; - "member get_IsMyNumber(this) (unitArg) = (if this.IsMyNumber then True else False) @ (10,5--10,13)"; "member get_Zero(unitVar0) = MyNumber(0) @ (12,25--12,35)"; "member op_Addition(_arg1,_arg2) = let x: Microsoft.FSharp.Core.int = _arg1.Item in let y: Microsoft.FSharp.Core.int = _arg2.Item in MyNumber(Operators.op_Addition (fun arg0_0 -> fun arg1_0 -> LanguagePrimitives.AdditionDynamic (arg0_0,arg1_0),x,y)) @ (13,23--13,33)"; "member DivideByInt(_arg3,i) = let x: Microsoft.FSharp.Core.int = _arg3.Item in MyNumber(Operators.op_Division (fun arg0_0 -> fun arg1_0 -> LanguagePrimitives.DivisionDynamic (arg0_0,arg1_0),x,i)) @ (15,31--15,41)"; @@ -3465,11 +3478,13 @@ let s2 = sign p1 let createOptions() = createOptionsAux [fileSource1] ["--langversion:7.0"] +[] +[] [] -let ``Test ProjectForWitnesses3`` () = +let ``Test ProjectForWitnesses3`` useTransparentCompiler = let cleanup, options = createOptionsAux [ ProjectForWitnesses3.fileSource1 ] ["--langversion:7.0"] use _holder = cleanup - let exprChecker = FSharpChecker.Create(keepAssemblyContents=true) + let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate for e in wholeProjectResults.Diagnostics do @@ -3496,11 +3511,13 @@ let ``Test ProjectForWitnesses3`` () = actual |> shouldPairwiseEqual expected +[] +[] [] -let ``Test ProjectForWitnesses3 GetWitnessPassingInfo`` () = +let ``Test ProjectForWitnesses3 GetWitnessPassingInfo`` useTransparentCompiler = let cleanup, options = ProjectForWitnesses3.createOptions() use _holder = cleanup - let exprChecker = FSharpChecker.Create(keepAssemblyContents=true) + let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate for e in wholeProjectResults.Diagnostics do @@ -3559,11 +3576,13 @@ let isNullQuoted (ts : 't[]) = let createOptions() = createOptionsAux [fileSource1] ["--langversion:7.0"] +[] +[] [] -let ``Test ProjectForWitnesses4 GetWitnessPassingInfo`` () = +let ``Test ProjectForWitnesses4 GetWitnessPassingInfo`` useTransparentCompiler = let cleanup, options = ProjectForWitnesses4.createOptions() use _holder = cleanup - let exprChecker = FSharpChecker.Create(keepAssemblyContents=true) + let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate for e in wholeProjectResults.Diagnostics do diff --git a/tests/service/ModuleReaderCancellationTests.fs b/tests/service/ModuleReaderCancellationTests.fs index 434ddca02db..a401c637fe6 100644 --- a/tests/service/ModuleReaderCancellationTests.fs +++ b/tests/service/ModuleReaderCancellationTests.fs @@ -135,7 +135,7 @@ let createPreTypeDefs typeData = |> Array.ofList |> Array.map (fun data -> PreTypeDef data :> ILPreTypeDef) -let referenceReaderProject getPreTypeDefs (cancelOnModuleAccess: bool) options = +let referenceReaderProject getPreTypeDefs (cancelOnModuleAccess: bool) (options: FSharpProjectOptions) = let reader = new ModuleReader("Reference", mkILTypeDefsComputed getPreTypeDefs, cancelOnModuleAccess) let project = FSharpReferencedProject.ILModuleReference( diff --git a/tests/service/MultiProjectAnalysisTests.fs b/tests/service/MultiProjectAnalysisTests.fs index eab86f98324..a306107eb36 100644 --- a/tests/service/MultiProjectAnalysisTests.fs +++ b/tests/service/MultiProjectAnalysisTests.fs @@ -23,6 +23,7 @@ open TestFramework let toIList (x: _ array) = x :> IList<_> let numProjectsForStressTest = 100 let internal checker = FSharpChecker.Create(projectCacheSize=numProjectsForStressTest + 10) +let internal transparentCompilerChecker = FSharpChecker.Create(projectCacheSize=numProjectsForStressTest + 10, useTransparentCompiler=true) /// Extract range info let internal tups (m:range) = (m.StartLine, m.StartColumn), (m.EndLine, m.EndColumn) @@ -67,9 +68,9 @@ type U = let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] + let fileNames = [|fileName1|] let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } @@ -95,9 +96,9 @@ let x = let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] + let fileNames = [|fileName1|] let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } // A project referencing two sub-projects @@ -120,11 +121,12 @@ let u = Case1 3 """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] + let fileNames = [|fileName1|] let args = mkProjectCommandLineArgs (dllName, fileNames) let options = - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } { options with + SourceFiles = fileNames OtherOptions = Array.append options.OtherOptions [| ("-r:" + Project1A.dllName); ("-r:" + Project1B.dllName) |] ReferencedProjects = [| FSharpReferencedProject.FSharpReference(Project1A.dllName, Project1A.options); FSharpReferencedProject.FSharpReference(Project1B.dllName, Project1B.options); |] } @@ -144,7 +146,11 @@ let ``Test multi project 1 basic`` () = |> shouldEqual ["p"; "c"; "u"] [] -let ``Test multi project 1 all symbols`` () = +[] +[] +let ``Test multi project 1 all symbols`` useTransparentCompiler = + + let checker = if useTransparentCompiler then transparentCompilerChecker else checker let p1A = checker.ParseAndCheckProject(Project1A.options) |> Async.RunImmediate let p1B = checker.ParseAndCheckProject(Project1B.options) |> Async.RunImmediate @@ -182,7 +188,11 @@ let ``Test multi project 1 all symbols`` () = usesOfx1FromProject1AInMultiProject1 |> shouldEqual usesOfx1FromMultiProject1InMultiProject1 [] -let ``Test multi project 1 xmldoc`` () = +[] +[] +let ``Test multi project 1 xmldoc`` useTransparentCompiler = + + let checker = if useTransparentCompiler then transparentCompilerChecker else checker let p1A = checker.ParseAndCheckProject(Project1A.options) |> Async.RunImmediate let p1B = checker.ParseAndCheckProject(Project1B.options) |> Async.RunImmediate @@ -284,9 +294,9 @@ let p = C.Print() let baseName = tryCreateTemporaryFileName () let dllName = Path.ChangeExtension(baseName, ".dll") let projFileName = Path.ChangeExtension(baseName, ".fsproj") - let fileNames = [fileName1 ] + let fileNames = [|fileName1|] let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } yield { ModuleName = moduleName; FileName=fileName1; Options = options; DllName=dllName } ] let jointProject = @@ -305,10 +315,10 @@ let p = (""" + String.concat ",\r\n " [ for p in projects -> p.ModuleName + ".v" ] + ")" FileSystem.OpenFileForWriteShim(fileName).Write(fileSource) - let fileNames = [fileName] + let fileNames = [|fileName|] let args = mkProjectCommandLineArgs (dllName, fileNames) let options = - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } { options with OtherOptions = Array.append options.OtherOptions [| for p in projects -> ("-r:" + p.DllName) |] ReferencedProjects = [| for p in projects -> FSharpReferencedProject.FSharpReference(p.DllName, p.Options); |] } @@ -319,14 +329,16 @@ let p = (""" |> function Some x -> x | None -> if a = jointProject.FileName then "fileN" else "??" - let makeCheckerForStressTest ensureBigEnough = + let makeCheckerForStressTest ensureBigEnough useTransparentCompiler = let size = (if ensureBigEnough then numProjectsForStressTest + 10 else numProjectsForStressTest / 2 ) - FSharpChecker.Create(projectCacheSize=size) + FSharpChecker.Create(projectCacheSize=size, useTransparentCompiler=useTransparentCompiler) [] -let ``Test ManyProjectsStressTest basic`` () = +[] +[] +let ``Test ManyProjectsStressTest basic`` useTransparentCompiler = - let checker = ManyProjectsStressTest.makeCheckerForStressTest true + let checker = ManyProjectsStressTest.makeCheckerForStressTest true useTransparentCompiler let wholeProjectResults = checker.ParseAndCheckProject(ManyProjectsStressTest.jointProject.Options) |> Async.RunImmediate @@ -338,9 +350,11 @@ let ``Test ManyProjectsStressTest basic`` () = |> shouldEqual ["p"] [] -let ``Test ManyProjectsStressTest cache too small`` () = +[] +[] +let ``Test ManyProjectsStressTest cache too small`` useTransparentCompiler = - let checker = ManyProjectsStressTest.makeCheckerForStressTest false + let checker = ManyProjectsStressTest.makeCheckerForStressTest false useTransparentCompiler let wholeProjectResults = checker.ParseAndCheckProject(ManyProjectsStressTest.jointProject.Options) |> Async.RunImmediate @@ -352,9 +366,11 @@ let ``Test ManyProjectsStressTest cache too small`` () = |> shouldEqual ["p"] [] -let ``Test ManyProjectsStressTest all symbols`` () = +[] +[] +let ``Test ManyProjectsStressTest all symbols`` useTransparentCompiler = - let checker = ManyProjectsStressTest.makeCheckerForStressTest true + let checker = ManyProjectsStressTest.makeCheckerForStressTest true useTransparentCompiler for i in 1 .. 10 do printfn "stress test iteration %d (first may be slow, rest fast)" i let projectsResults = [ for p in ManyProjectsStressTest.projects -> p, checker.ParseAndCheckProject(p.Options) |> Async.RunImmediate ] @@ -397,11 +413,11 @@ let x = "F#" let cleanFileName a = if a = fileName1 then "Project1" else "??" - let fileNames = [fileName1] + let fileNames = [|fileName1|] let getOptions() = let args = mkProjectCommandLineArgs (dllName, fileNames) - checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } module internal MultiProjectDirty2 = @@ -422,17 +438,21 @@ let z = Project1.x let cleanFileName a = if a = fileName1 then "Project2" else "??" - let fileNames = [fileName1] + let fileNames = [|fileName1|] let getOptions() = let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } { options with OtherOptions = Array.append options.OtherOptions [| ("-r:" + MultiProjectDirty1.dllName) |] ReferencedProjects = [| FSharpReferencedProject.FSharpReference(MultiProjectDirty1.dllName, MultiProjectDirty1.getOptions()) |] } [] -let ``Test multi project symbols should pick up changes in dependent projects`` () = +[] +[] +let ``Test multi project symbols should pick up changes in dependent projects`` useTransparentCompiler = + + let checker = if useTransparentCompiler then transparentCompilerChecker else checker // register to count the file checks let count = ref 0 @@ -614,9 +634,9 @@ type C() = let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] + let fileNames = [|fileName1|] let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } //Project2A.fileSource1 // A project referencing Project2A @@ -633,10 +653,10 @@ let v = Project2A.C().InternalMember // access an internal symbol """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, [||]) let options = - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } { options with OtherOptions = Array.append options.OtherOptions [| ("-r:" + Project2A.dllName); |] ReferencedProjects = [| FSharpReferencedProject.FSharpReference(Project2A.dllName, Project2A.options); |] } @@ -657,17 +677,21 @@ let v = Project2A.C().InternalMember // access an internal symbol """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, [||]) let options = - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } { options with OtherOptions = Array.append options.OtherOptions [| ("-r:" + Project2A.dllName); |] ReferencedProjects = [| FSharpReferencedProject.FSharpReference(Project2A.dllName, Project2A.options); |] } let cleanFileName a = if a = fileName1 then "file1" else "??" [] -let ``Test multi project2 errors`` () = +[] +[] +let ``Test multi project2 errors`` useTransparentCompiler = + + let checker = if useTransparentCompiler then transparentCompilerChecker else checker let wholeProjectResults = checker.ParseAndCheckProject(Project2B.options) |> Async.RunImmediate for e in wholeProjectResults.Diagnostics do @@ -725,9 +749,9 @@ let (|DivisibleBy|_|) by n = let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] + let fileNames = [|fileName1|] let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } // A project referencing a sub-project @@ -750,17 +774,22 @@ let fizzBuzz = function """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, [||]) let options = - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } { options with + SourceFiles = fileNames OtherOptions = Array.append options.OtherOptions [| ("-r:" + Project3A.dllName) |] ReferencedProjects = [| FSharpReferencedProject.FSharpReference(Project3A.dllName, Project3A.options) |] } let cleanFileName a = if a = fileName1 then "file1" else "??" [] -let ``Test multi project 3 whole project errors`` () = +[] +[] +let ``Test multi project 3 whole project errors`` useTransparentCompiler = + + let checker = if useTransparentCompiler then transparentCompilerChecker else checker let wholeProjectResults = checker.ParseAndCheckProject(MultiProject3.options) |> Async.RunImmediate for e in wholeProjectResults.Diagnostics do @@ -769,7 +798,11 @@ let ``Test multi project 3 whole project errors`` () = wholeProjectResults.Diagnostics.Length |> shouldEqual 0 [] -let ``Test active patterns' XmlDocSig declared in referenced projects`` () = +[] +[] +let ``Test active patterns' XmlDocSig declared in referenced projects`` useTransparentCompiler = + + let checker = if useTransparentCompiler then transparentCompilerChecker else checker let wholeProjectResults = checker.ParseAndCheckProject(MultiProject3.options) |> Async.RunImmediate let backgroundParseResults1, backgroundTypedParse1 = diff --git a/tests/service/PatternMatchCompilationTests.fs b/tests/service/PatternMatchCompilationTests.fs index 04da829f524..c75225aae0c 100644 --- a/tests/service/PatternMatchCompilationTests.fs +++ b/tests/service/PatternMatchCompilationTests.fs @@ -611,16 +611,17 @@ let x as () = y let z as """ dumpDiagnostics checkResults |> shouldEqual [ - "(10,9--10,10): Unexpected symbol ',' in binding"; - "(11,9--11,10): Unexpected symbol ':' in binding"; - "(12,9--12,11): Unexpected symbol '::' in binding"; - "(13,9--13,10): Unexpected symbol '&' in binding"; - "(14,9--14,10): Unexpected symbol '|' in binding"; + "(10,6--10,8): Expecting pattern"; + "(11,6--11,8): Expecting pattern"; + "(12,6--12,8): Expecting pattern"; + "(13,6--13,8): Expecting pattern"; + "(14,6--14,8): Expecting pattern"; "(15,13--15,14): Unexpected symbol '=' in pattern. Expected ')' or other token."; "(15,9--15,10): Unmatched '('"; "(16,0--16,3): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (15:1). Try indenting this further.\u001dTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7."; "(17,16--17,17): Unexpected identifier in pattern. Expected '(' or other token."; - "(20,0--20,0): Incomplete structured construct at or before this point in binding"; + "(19,6--19,8): Expecting pattern"; + "(20,0--20,0): Incomplete structured construct at or before this point in binding. Expected '=' or other token."; "(3,13--3,17): This expression was expected to have type\u001d 'int' \u001dbut here has type\u001d 'bool'"; "(3,4--3,10): Incomplete pattern matches on this expression. For example, the value '0' may indicate a case not covered by the pattern(s)."; "(4,16--4,17): This expression was expected to have type\u001d 'bool' \u001dbut here has type\u001d 'int'"; @@ -629,6 +630,11 @@ let z as "(6,9--6,15): This runtime coercion or type test from type\u001d 'a \u001d to \u001d int \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."; "(8,29--8,30): This expression was expected to have type\u001d 'unit' \u001dbut here has type\u001d 'int'"; "(9,26--9,27): This expression was expected to have type\u001d 'unit' \u001dbut here has type\u001d 'int'"; + "(10,15--10,16): This expression was expected to have type\u001d ''a * 'b' \u001dbut here has type\u001d 'int'"; + "(11,11--11,12): The type 'k' is not defined."; + "(12,16--12,18): This expression was expected to have type\u001d ''a list' \u001dbut here has type\u001d 'int'"; + "(12,4--12,13): Incomplete pattern matches on this expression. For example, the value '[]' may indicate a case not covered by the pattern(s)."; + "(14,4--14,12): The two sides of this 'or' pattern bind different sets of variables"; "(18,14--18,15): The value or constructor 'y' is not defined." ] @@ -943,16 +949,17 @@ let :? x as () = y let :? z as """ dumpDiagnostics checkResults |> shouldEqual [ - "(10,12--10,13): Unexpected symbol ',' in binding"; - "(11,12--11,13): Unexpected symbol ':' in binding"; - "(12,12--12,14): Unexpected symbol '::' in binding"; - "(13,12--13,13): Unexpected symbol '&' in binding"; - "(14,12--14,13): Unexpected symbol '|' in binding"; + "(10,9--10,11): Expecting pattern"; + "(11,9--11,11): Expecting pattern"; + "(12,9--12,11): Expecting pattern"; + "(13,9--13,11): Expecting pattern"; + "(14,9--14,11): Expecting pattern"; "(15,16--15,17): Unexpected symbol '=' in pattern. Expected ')' or other token."; "(15,12--15,13): Unmatched '('"; "(16,0--16,3): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (15:1). Try indenting this further.\u001dTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7."; "(17,19--17,20): Unexpected identifier in pattern. Expected '(' or other token."; - "(20,0--20,0): Incomplete structured construct at or before this point in binding"; + "(19,9--19,11): Expecting pattern"; + "(20,0--20,0): Incomplete structured construct at or before this point in binding. Expected '=' or other token."; "(3,7--3,8): The type 'a' is not defined."; "(3,4--3,8): This runtime coercion or type test from type\u001d 'a \u001d to \u001d 'b \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."; "(4,7--4,8): The type 'b' is not defined."; @@ -967,10 +974,26 @@ let :? z as "(8,4--8,8): This runtime coercion or type test from type\u001d 'a \u001d to \u001d 'b \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."; "(9,7--9,8): The type 'g' is not defined."; "(9,4--9,8): This runtime coercion or type test from type\u001d 'a \u001d to \u001d 'b \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."; + "(10,7--10,8): The type 'h' is not defined."; + "(10,4--10,8): This runtime coercion or type test from type\u001d 'a \u001d to \u001d 'b \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."; + "(10,7--10,8): The type 'h' is not defined."; + "(10,4--10,8): This runtime coercion or type test from type\u001d 'a \u001d to \u001d 'b \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."; + "(11,7--11,8): The type 'j' is not defined."; + "(11,4--11,8): This runtime coercion or type test from type\u001d 'a \u001d to \u001d 'b \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."; + "(12,7--12,8): The type 'l' is not defined."; + "(12,4--12,8): This runtime coercion or type test from type\u001d 'a \u001d to \u001d 'b \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."; + "(13,7--13,8): The type 'n' is not defined."; + "(13,4--13,8): This runtime coercion or type test from type\u001d 'a \u001d to \u001d 'b \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."; + "(14,7--14,8): The type 'p' is not defined."; + "(14,4--14,8): This runtime coercion or type test from type\u001d 'a \u001d to \u001d 'b \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."; "(15,7--15,8): The type 'r' is not defined."; "(15,4--15,8): This runtime coercion or type test from type\u001d 'a \u001d to \u001d 'b \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."; + "(17,7--17,8): The type 'v' is not defined."; + "(17,4--17,8): This runtime coercion or type test from type\u001d 'a \u001d to \u001d 'b \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."; "(18,7--18,8): The type 'x' is not defined."; - "(18,4--18,8): This runtime coercion or type test from type\u001d 'a \u001d to \u001d 'b \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed." + "(18,4--18,8): This runtime coercion or type test from type\u001d 'a \u001d to \u001d 'b \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."; + "(19,7--19,8): The type 'z' is not defined."; + "(19,4--19,8): This runtime coercion or type test from type\u001d 'a \u001d to \u001d 'b \u001dinvolves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed." ] [] @@ -1207,7 +1230,8 @@ let y as ?z = 8 () """ dumpDiagnostics checkResults |> shouldEqual [ - "(7,9--7,11): Unexpected symbol '[<' in binding" + "(7,6--7,8): Expecting pattern"; + "(7,9--7,11): Unexpected symbol '[<' in binding. Expected '=' or other token." "(8,4--8,11): This is not a valid pattern" "(8,4--8,16): Incomplete pattern matches on this expression." "(9,9--9,16): This is not a valid pattern" diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index dab349fd0ab..a1a58a709b2 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -90,9 +90,10 @@ let mmmm2 : M.CAbbrev = new M.CAbbrev() // note, these don't count as uses of C FileSystem.OpenFileForWriteShim(fileName2).Write(fileSource2Text) let fileNames = [fileName1; fileName2] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) - let parsingOptions, _ = checker.GetParsingOptionsFromCommandLineArgs(List.ofArray args) + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames |> List.toArray } + let parsingOptions', _ = checker.GetParsingOptionsFromCommandLineArgs(List.ofArray args) + let parsingOptions = { parsingOptions' with SourceFiles = fileNames |> List.toArray } let cleanFileName a = if a = fileName1 then "file1" else if a = fileName2 then "file2" else "??" [] @@ -675,9 +676,9 @@ let _ = GenericFunction(3, 4) """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } @@ -713,11 +714,11 @@ let ``Test project2 all symbols in signature`` () = "DUWithNormalFields"; "member get_IsD"; "member get_IsDU1"; "member get_IsDU2"; "property IsD"; "property IsDU1"; "property IsDU2"; "DU1"; "field Item1"; "field Item2"; "DU2"; "field Item1"; "field Item2"; "D"; "field Item1"; - "field Item2"; "DUWithNamedFields"; "member get_IsDU"; "property IsDU"; "DU"; + "field Item2"; "DUWithNamedFields"; "DU"; "field x"; "field y"; "GenericClass`1"; "generic parameter T"; "member .ctor"; "member GenericMethod"; "generic parameter U"] |> List.sort - shouldEqual e r + shouldPairwiseEqual e r [] let ``Test project2 all uses of all signature symbols`` () = @@ -735,12 +736,10 @@ let ``Test project2 all uses of all signature symbols`` () = ("generic parameter T", [("file1", ((22, 23), (22, 25))); ("file1", ((22, 30), (22, 32))); ("file1", ((22, 45), (22, 47))); ("file1", ((22, 50), (22, 52)))]); - ("member get_IsD", []); - ("member get_IsDU", []); + ("member get_IsD", []); ("member get_IsDU1", []); ("member get_IsDU2", []); - ("property IsD", []); - ("property IsDU", []); + ("property IsD", []); ("property IsDU1", []); ("property IsDU2", []); ("DUWithNormalFields", [("file1", ((3, 5), (3, 23)))]); @@ -928,9 +927,9 @@ let getM (foo: IFoo) = foo.InterfaceMethod("d") """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } @@ -1297,9 +1296,9 @@ let inline twice(x : ^U, y : ^U) = x + y """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } @@ -1471,9 +1470,9 @@ let parseNumeric str = let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -1683,9 +1682,9 @@ let f () = let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -1739,9 +1738,9 @@ let x2 = C.M(arg1 = 3, arg2 = 4, ?arg3 = Some 5) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -1800,9 +1799,9 @@ let x = let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -1880,9 +1879,9 @@ let inline check< ^T when ^T : (static member IsInfinity : ^T -> bool)> (num: ^T let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -1959,9 +1958,9 @@ C.M("http://goo", query = 1) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -2039,9 +2038,9 @@ let fff (x:System.Collections.Generic.Dictionary.Enumerator) = () let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -2108,9 +2107,9 @@ let x2 = query { for i in 0 .. 100 do let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -2175,9 +2174,9 @@ let x3 = new System.DateTime() let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -2334,9 +2333,9 @@ let x2 = S(3) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -2401,9 +2400,9 @@ let f x = let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -2488,9 +2487,9 @@ and G = Case1 | Case2 of int FileSystem.OpenFileForWriteShim(sigFileName1).Write(sigFileSource1Text) let cleanFileName a = if a = fileName1 then "file1" elif a = sigFileName1 then "sig1" else "??" - let fileNames = [sigFileName1; fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|sigFileName1; fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -2754,9 +2753,9 @@ let f3 (x: System.Exception) = x.HelpLink <- "" // check use of .NET setter prop FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -2841,9 +2840,9 @@ let _ = list<_>.Empty FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -2897,9 +2896,9 @@ let s = System.DayOfWeek.Monday FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -2972,9 +2971,9 @@ type A<'T>() = FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -3033,9 +3032,9 @@ let _ = { new IMyInterface with FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -3107,9 +3106,9 @@ let f5 (x: int[,,]) = () // test a multi-dimensional array FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } @@ -3254,9 +3253,9 @@ module Setter = FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] let ``Test Project23 whole project errors`` () = @@ -3425,9 +3424,9 @@ TypeWithProperties.StaticAutoPropGetSet <- 3 FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] let ``Test Project24 whole project errors`` () = @@ -3682,12 +3681,12 @@ let _ = XmlProvider<"13">.GetSample() FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] + let fileNames = [|fileName1|] let args = - [| yield! mkProjectCommandLineArgs (dllName, fileNames) + [| yield! mkProjectCommandLineArgs (dllName, []) yield @"-r:" + Path.Combine(__SOURCE_DIRECTORY__, Path.Combine("data", "FSharp.Data.dll")) yield @"-r:" + sysLib "System.Xml.Linq" |] - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] #if NETCOREAPP @@ -3822,9 +3821,9 @@ type Class() = let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -3912,9 +3911,9 @@ type CFooImpl() = """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] let ``Test project27 whole project errors`` () = @@ -3977,9 +3976,9 @@ type Use() = """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } #if !NO_TYPEPROVIDERS [] let ``Test project28 all symbols in signature`` () = @@ -4055,9 +4054,9 @@ let f (x: INotifyPropertyChanged) = failwith "" """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -4114,9 +4113,9 @@ type T() = """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } let ``Test project30 whole project errors`` () = @@ -4174,10 +4173,9 @@ let g = Console.ReadKey() """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } let ``Test project31 whole project errors`` () = let wholeProjectResults = checker.ParseAndCheckProject(Project31.options) |> Async.RunImmediate @@ -4317,9 +4315,9 @@ val func : int -> int FileSystem.OpenFileForWriteShim(sigFileName1).Write(sigFileSource1) let cleanFileName a = if a = fileName1 then "file1" elif a = sigFileName1 then "sig1" else "??" - let fileNames = [sigFileName1; fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|sigFileName1; fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -4385,9 +4383,9 @@ type System.Int32 with FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] let ``Test Project33 whole project errors`` () = @@ -4424,17 +4422,17 @@ module internal Project34 = FileSystem.OpenFileForWriteShim(sourceFileName).Write(fileSource) let cleanFileName a = if a = sourceFileName then "file1" else "??" - let fileNames = [sourceFileName] + let fileNames = [|sourceFileName|] let args = [| - yield! mkProjectCommandLineArgs (dllName, fileNames) + yield! mkProjectCommandLineArgs (dllName, []) // We use .NET-built version of System.Data.dll since the tests depend on implementation details // i.e. the private type System.Data.Listeners may not be available on Mono. yield @"-r:" + Path.Combine(__SOURCE_DIRECTORY__, Path.Combine("data", "System.Data.dll")) |] |> Array.filter(fun arg -> not((arg.Contains("System.Data")) && not (arg.Contains(@"service\data\System.Data.dll")))) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] let ``Test Project34 whole project errors`` () = @@ -4502,9 +4500,9 @@ type Test = FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] @@ -4574,13 +4572,13 @@ module internal Project35b = FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1Text) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] + let fileNames = [|fileName1|] #if NETCOREAPP let projPath = Path.ChangeExtension(fileName1, ".fsproj") let dllPath = Path.ChangeExtension(fileName1, ".dll") let args = mkProjectCommandLineArgs(dllPath, fileNames) let args2 = Array.append args [| "-r:notexist.dll" |] - let options = checker.GetProjectOptionsFromCommandLineArgs (projPath, args2) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projPath, args2) with SourceFiles = fileNames } #else let options = checker.GetProjectOptionsFromScript(fileName1, fileSource1) |> Async.RunImmediate |> fst #endif @@ -4641,13 +4639,15 @@ let callToOverload = B(5).Overload(4) FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) let cleanFileName a = if a = fileName1 then "file1" else "??" - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) [] -let ``Test project36 FSharpMemberOrFunctionOrValue.IsBaseValue`` () = - let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true) - let options = keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (Project36.projFileName, Project36.args) +[] +[] +let ``Test project36 FSharpMemberOrFunctionOrValue.IsBaseValue`` useTransparentCompiler = + let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) + let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (Project36.projFileName, Project36.args) with SourceFiles = Project36.fileNames } let wholeProjectResults = keepAssemblyContentsChecker.ParseAndCheckProject(options) |> Async.RunImmediate @@ -4660,9 +4660,11 @@ let ``Test project36 FSharpMemberOrFunctionOrValue.IsBaseValue`` () = |> fun baseSymbol -> shouldEqual true baseSymbol.IsBaseValue [] -let ``Test project36 FSharpMemberOrFunctionOrValue.IsConstructorThisValue & IsMemberThisValue`` () = - let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true) - let options = keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (Project36.projFileName, Project36.args) +[] +[] +let ``Test project36 FSharpMemberOrFunctionOrValue.IsConstructorThisValue & IsMemberThisValue`` useTransparentCompiler = + let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) + let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (Project36.projFileName, Project36.args) with SourceFiles = Project36.fileNames } let wholeProjectResults = keepAssemblyContentsChecker.ParseAndCheckProject(options) |> Async.RunImmediate let declarations = let checkedFile = wholeProjectResults.AssemblyContents.ImplementationFiles[0] @@ -4697,9 +4699,11 @@ let ``Test project36 FSharpMemberOrFunctionOrValue.IsConstructorThisValue & IsMe |> shouldEqual true [] -let ``Test project36 FSharpMemberOrFunctionOrValue.LiteralValue`` () = - let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true) - let options = keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (Project36.projFileName, Project36.args) +[] +[] +let ``Test project36 FSharpMemberOrFunctionOrValue.LiteralValue`` useTransparentCompiler = + let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) + let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (Project36.projFileName, Project36.args) with SourceFiles = Project36.fileNames } let wholeProjectResults = keepAssemblyContentsChecker.ParseAndCheckProject(options) |> Async.RunImmediate let project36Module = wholeProjectResults.AssemblySignature.Entities[0] let lit = project36Module.MembersFunctionsAndValues[0] @@ -4760,9 +4764,9 @@ namespace AttrTests do () """ FileSystem.OpenFileForWriteShim(fileName2).Write(fileSource2) - let fileNames = [fileName1; fileName2] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1; fileName2|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] let ``Test project37 typeof and arrays in attribute constructor arguments`` () = @@ -4902,9 +4906,9 @@ type A<'XX, 'YY>() = member this.Property = 1 """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] let ``Test project38 abstract slot information`` () = @@ -4988,9 +4992,9 @@ let uses () = C().CurriedMemberWithIncompleteSignature (failwith "x1") (failwith "x2") (failwith "x3", failwith "x4") """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } let cleanFileName a = if a = fileName1 then "file1" else "??" [] @@ -5063,9 +5067,9 @@ let g (x: C) = x.IsItAnA,x.IsItAnAMethod() """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } let cleanFileName a = if a = fileName1 then "file1" else "??" [] @@ -5134,9 +5138,9 @@ module M if true then Foo else Bar """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } let cleanFileName a = if a = fileName1 then "file1" else "??" [] @@ -5226,9 +5230,9 @@ open File1 let test2() = test() """ FileSystem.OpenFileForWriteShim(fileName2).Write(fileSource2) - let fileNames = [fileName1;fileName2] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1;fileName2|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] let ``Test project42 to ensure cached checked results are invalidated`` () = @@ -5261,21 +5265,21 @@ module internal ProjectBig = let fileSources2 = [ for i,f in fileSources -> SourceText.ofString f ] let fileNames = [ for _,f in fileNamesI -> f ] - let args = mkProjectCommandLineArgs (dllName, fileNames) + let args = mkProjectCommandLineArgs (dllName, []) let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) - let parsingOptions, _ = checker.GetParsingOptionsFromCommandLineArgs(List.ofArray args) - + let parsingOptions', _ = checker.GetParsingOptionsFromCommandLineArgs(List.ofArray args) + let parsingOptions = { parsingOptions' with SourceFiles = fileNames |> List.toArray } [] // Simplified repro for https://github.com/dotnet/fsharp/issues/2679 let ``add files with same name from different folders`` () = let fileNames = - [ __SOURCE_DIRECTORY__ + "/data/samename/folder1/a.fs" - __SOURCE_DIRECTORY__ + "/data/samename/folder2/a.fs" ] + [| __SOURCE_DIRECTORY__ + "/data/samename/folder1/a.fs" + __SOURCE_DIRECTORY__ + "/data/samename/folder2/a.fs" |] let projFileName = __SOURCE_DIRECTORY__ + "/data/samename/tempet.fsproj" let args = mkProjectCommandLineArgs ("test.dll", fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } let wholeProjectResults = checker.ParseAndCheckProject(options) |> Async.RunImmediate let errors = wholeProjectResults.Diagnostics @@ -5308,13 +5312,15 @@ let foo (a: Foo): bool = """ FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] -let ``Test typed AST for struct unions`` () = // See https://github.com/fsharp/FSharp.Compiler.Service/issues/756 - let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true) +[] +[] +let ``Test typed AST for struct unions`` useTransparentCompiler = // See https://github.com/fsharp/FSharp.Compiler.Service/issues/756 + let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) let wholeProjectResults = keepAssemblyContentsChecker.ParseAndCheckProject(ProjectStructUnions.options) |> Async.RunImmediate let declarations = @@ -5350,9 +5356,9 @@ let x = (1 = 3.0) """ let fileSource1 = SourceText.ofString fileSource1Text FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1Text) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [| fileName1 |] + let args = mkProjectCommandLineArgs (dllName, []) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } [] let ``Test diagnostics with line directives active`` () = @@ -5401,7 +5407,9 @@ let ``Test diagnostics with line directives ignored`` () = //------------------------------------------------------ [] -let ``ParseAndCheckFileResults contains ImplFile list if FSharpChecker is created with keepAssemblyContent flag set to true``() = +[] +[] +let ``ParseAndCheckFileResults contains ImplFile list if FSharpChecker is created with keepAssemblyContent flag set to true`` useTransparentCompiler = let fileName1 = Path.ChangeExtension(tryCreateTemporaryFileName (), ".fs") let base2 = tryCreateTemporaryFileName () @@ -5414,10 +5422,10 @@ type A(i:int) = let fileSource1 = SourceText.ofString fileSource1Text FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1Text) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true) - let options = keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) + let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } let fileCheckResults = keepAssemblyContentsChecker.ParseAndCheckFileInProject(fileName1, 0, fileSource1, options) |> Async.RunImmediate @@ -5459,7 +5467,9 @@ let ``#4030, Incremental builder creation warnings`` (args, errorSeverities) = //------------------------------------------------------ [] -let ``Unused opens in rec module smoke test 1``() = +[] +[] +let ``Unused opens in rec module smoke test 1`` useTransparentCompiler = let fileName1 = Path.ChangeExtension(tryCreateTemporaryFileName (), ".fs") let base2 = tryCreateTemporaryFileName () @@ -5505,10 +5515,10 @@ type UseTheThings(i:int) = let fileSource1 = SourceText.ofString fileSource1Text FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1Text) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true) - let options = keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) + let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } let fileCheckResults = keepAssemblyContentsChecker.ParseAndCheckFileInProject(fileName1, 0, fileSource1, options) |> Async.RunImmediate @@ -5532,7 +5542,9 @@ type UseTheThings(i:int) = unusedOpensData |> shouldEqual expected [] -let ``Unused opens in non rec module smoke test 1``() = +[] +[] +let ``Unused opens in non rec module smoke test 1`` useTransparentCompiler = let fileName1 = Path.ChangeExtension(tryCreateTemporaryFileName (), ".fs") let base2 = tryCreateTemporaryFileName () @@ -5578,10 +5590,10 @@ type UseTheThings(i:int) = let fileSource1 = SourceText.ofString fileSource1Text FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1Text) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true) - let options = keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) + let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } let fileCheckResults = keepAssemblyContentsChecker.ParseAndCheckFileInProject(fileName1, 0, fileSource1, options) |> Async.RunImmediate @@ -5605,7 +5617,9 @@ type UseTheThings(i:int) = unusedOpensData |> shouldEqual expected [] -let ``Unused opens smoke test auto open``() = +[] +[] +let ``Unused opens smoke test auto open`` useTransparentCompiler = let fileName1 = Path.ChangeExtension(tryCreateTemporaryFileName (), ".fs") let base2 = tryCreateTemporaryFileName () @@ -5659,10 +5673,10 @@ module M2 = let fileSource1 = SourceText.ofString fileSource1Text FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1Text) - let fileNames = [fileName1] - let args = mkProjectCommandLineArgs (dllName, fileNames) - let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true) - let options = keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (projFileName, args) + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler) + let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } let fileCheckResults = keepAssemblyContentsChecker.ParseAndCheckFileInProject(fileName1, 0, fileSource1, options) |> Async.RunImmediate diff --git a/tests/service/ScriptOptionsTests.fs b/tests/service/ScriptOptionsTests.fs index 6b692543572..4cdeaa5c3c2 100644 --- a/tests/service/ScriptOptionsTests.fs +++ b/tests/service/ScriptOptionsTests.fs @@ -50,9 +50,9 @@ let ``can generate options for different frameworks regardless of execution envi [] [] let ``can resolve nuget packages to right target framework for different frameworks regardless of execution environment``(flags) = - let path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + let path = DirectoryInfo(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)) let file = tryCreateTemporaryFileNameInDirectory(path) + ".fsx" - let scriptFullPath = Path.Combine(path, file) + let scriptFullPath = Path.Combine(path.FullName, file) let scriptSource = """ #r "nuget: FSharp.Data, 3.3.3" open System diff --git a/tests/service/ServiceUntypedParseTests.fs b/tests/service/ServiceUntypedParseTests.fs index 7255773d2e0..25417a31d96 100644 --- a/tests/service/ServiceUntypedParseTests.fs +++ b/tests/service/ServiceUntypedParseTests.fs @@ -839,7 +839,7 @@ add2 1 2 | Some range -> range |> tups - |> shouldEqual ((3, 18), (3, 18)) + |> shouldEqual ((3, 17), (3, 18)) [] let ``TryRangeOfFunctionOrMethodBeingApplied - inside CE``() = diff --git a/tests/service/Symbols.fs b/tests/service/Symbols.fs index f4c417c909d..b3d6261d60a 100644 --- a/tests/service/Symbols.fs +++ b/tests/service/Symbols.fs @@ -301,6 +301,75 @@ type E = Ns1.Ns2.T | _ -> Assert.Fail (sprintf "Couldn't get entity: %s" symbolName)) + [] + let ``Interface 01`` () = + let _, checkResults = getParseAndCheckResults """ +open System + +IDisposable +""" + findSymbolUseByName "IDisposable" checkResults |> ignore + + [] + let ``Interface 02`` () = + let _, checkResults = getParseAndCheckResults """ +System.IDisposable +""" + findSymbolUseByName "IDisposable" checkResults |> ignore + + [] + let ``Interface 03`` () = + let _, checkResults = getParseAndCheckResults """ +open System + +{ new IDisposable with } +""" + findSymbolUseByName "IDisposable" checkResults |> ignore + + + [] + let ``Interface 04 - Type arg`` () = + let _, checkResults = getParseAndCheckResults """ +open System.Collections.Generic + +IList +""" + let symbolUse = findSymbolUseByName "IList`1" checkResults + let _, typeArg = symbolUse.GenericArguments[0] + typeArg.Format(symbolUse.DisplayContext) |> shouldEqual "int" + + [] + let ``Interface 05 - Type arg`` () = + let _, checkResults = getParseAndCheckResults """ +type I<'T> = + abstract M: 'T -> unit + +{ new I<_> with + member this.M(i: int) = () } +""" + let symbolUse = + getSymbolUses checkResults + |> Seq.findBack (fun symbolUse -> symbolUse.Symbol.DisplayName = "I") + + let _, typeArg = symbolUse.GenericArguments[0] + typeArg.Format(symbolUse.DisplayContext) |> shouldEqual "int" + + [] + let ``Interface 06 - Type arg`` () = + let _, checkResults = getParseAndCheckResults """ +type I<'T> = + abstract M: 'T -> unit + +{ new I with + member this.M _ = () } +""" + let symbolUse = + getSymbolUses checkResults + |> Seq.findBack (fun symbolUse -> symbolUse.Symbol.DisplayName = "I") + + let _, typeArg = symbolUse.GenericArguments[0] + typeArg.Format(symbolUse.DisplayContext) |> shouldEqual "int" + [] let ``FSharpType.Format can use prefix representations`` () = let _, checkResults = getParseAndCheckResults """ @@ -1123,3 +1192,14 @@ let z = builder if symbolUse.Symbol.DisplayName = "builder" then (symbolUse.Range.StartLine, symbolUse.Range.StartColumn), symbolUse.IsFromComputationExpression ] + +module Member = + [] + let ``Inherit 01`` () = + let _, checkResults = getParseAndCheckResults """ +type T() = + inherit Foo() + + let i = 1 +""" + assertHasSymbolUsages ["i"] checkResults diff --git a/tests/service/data/SyntaxTree/Binding/RangeOfAttributeShouldBeIncludedInSecondaryConstructor.fs.bsl b/tests/service/data/SyntaxTree/Binding/RangeOfAttributeShouldBeIncludedInSecondaryConstructor.fs.bsl index 2b1943b2d20..ceff4f8e244 100644 --- a/tests/service/data/SyntaxTree/Binding/RangeOfAttributeShouldBeIncludedInSecondaryConstructor.fs.bsl +++ b/tests/service/data/SyntaxTree/Binding/RangeOfAttributeShouldBeIncludedInSecondaryConstructor.fs.bsl @@ -16,7 +16,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None }); Member @@ -109,7 +109,7 @@ ImplFile (3,4--11,12)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None })), (2,5--11,12), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInMemberBinding.fs.bsl b/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInMemberBinding.fs.bsl index e76316e2210..9e0bd27f359 100644 --- a/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInMemberBinding.fs.bsl +++ b/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInMemberBinding.fs.bsl @@ -13,7 +13,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None }); Member @@ -41,7 +41,7 @@ ImplFile (3,4--3,21)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None })), (2,5--3,21), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInMemberBindingWithParameters.fs.bsl b/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInMemberBindingWithParameters.fs.bsl index b9aa74e11b9..463fcef24ba 100644 --- a/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInMemberBindingWithParameters.fs.bsl +++ b/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInMemberBindingWithParameters.fs.bsl @@ -16,7 +16,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None }); Member @@ -48,7 +48,7 @@ ImplFile (3,4--3,24)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None })), (2,5--3,24), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInMemberBindingWithReturnType.fs.bsl b/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInMemberBindingWithReturnType.fs.bsl index 2458900141d..49eeec4d346 100644 --- a/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInMemberBindingWithReturnType.fs.bsl +++ b/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInMemberBindingWithReturnType.fs.bsl @@ -16,7 +16,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None }); Member @@ -57,7 +57,7 @@ ImplFile (3,4--3,33)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None })), (2,5--3,33), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInProperty.fs.bsl b/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInProperty.fs.bsl index 92929b73a08..32f9f50c83a 100644 --- a/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInProperty.fs.bsl +++ b/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInProperty.fs.bsl @@ -13,7 +13,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None }); GetSetMember @@ -88,7 +88,7 @@ ImplFile (3,4--5,50)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None })), (2,5--5,50), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/Expression/Object - Class 08.fs.bsl b/tests/service/data/SyntaxTree/Expression/Object - Class 08.fs.bsl index b4a5df07136..da2aa3f44bc 100644 --- a/tests/service/data/SyntaxTree/Expression/Object - Class 08.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Object - Class 08.fs.bsl @@ -24,7 +24,7 @@ ImplFile SynArgInfo ([], false, None)), None), Named (SynIdent (this, None), false, None, (4,12--4,16)), None, ArbitraryAfterError ("memberCore2", (4,16--4,16)), - (4,12--4,19), NoneAtInvisible, + (4,12--4,16), NoneAtInvisible, { LeadingKeyword = Member (4,5--4,11) InlineKeyword = None EqualsRange = None }), (4,5--4,16))], [], (3,2--3,9), diff --git a/tests/service/data/SyntaxTree/Expression/Object - Class 13.fs.bsl b/tests/service/data/SyntaxTree/Expression/Object - Class 13.fs.bsl index 3e636b4785c..6567abe2e7b 100644 --- a/tests/service/data/SyntaxTree/Expression/Object - Class 13.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Object - Class 13.fs.bsl @@ -24,7 +24,7 @@ ImplFile SynArgInfo ([], false, None)), None), Named (SynIdent (this, None), false, None, (4,12--4,16)), None, ArbitraryAfterError ("memberCore1", (4,16--4,16)), - (4,12--5,5), NoneAtInvisible, + (4,12--4,16), NoneAtInvisible, { LeadingKeyword = Member (4,5--4,11) InlineKeyword = None EqualsRange = None }), (4,5--4,16)); diff --git a/tests/service/data/SyntaxTree/Expression/SynExprObjWithSetter.fs.bsl b/tests/service/data/SyntaxTree/Expression/SynExprObjWithSetter.fs.bsl index 717ef3af2f2..8e4beda60ed 100644 --- a/tests/service/data/SyntaxTree/Expression/SynExprObjWithSetter.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/SynExprObjWithSetter.fs.bsl @@ -20,7 +20,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (3,9--3,11)), None, + (None, [], Const (Unit, (3,9--3,11)), None, PreXmlDoc ((3,9), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,9), { AsKeyword = None }); AbstractSlot @@ -46,7 +46,7 @@ ImplFile (4,4--4,54)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (3,9--3,11)), None, + (None, [], Const (Unit, (3,9--3,11)), None, PreXmlDoc ((3,9), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,9), { AsKeyword = None })), (2,0--4,54), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 02.fs.bsl index 669efb602f1..d85ff5016bd 100644 --- a/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Unfinished escaped ident 02.fs.bsl @@ -13,7 +13,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None }); Member @@ -73,7 +73,7 @@ ImplFile (4,4--6,27)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--6,27), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/LeadingKeyword/NewKeyword.fs.bsl b/tests/service/data/SyntaxTree/LeadingKeyword/NewKeyword.fs.bsl index bc62b3fc078..1e408d27f4b 100644 --- a/tests/service/data/SyntaxTree/LeadingKeyword/NewKeyword.fs.bsl +++ b/tests/service/data/SyntaxTree/LeadingKeyword/NewKeyword.fs.bsl @@ -13,7 +13,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None }); Member @@ -53,7 +53,7 @@ ImplFile (3,4--3,30)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None })), (2,5--3,30), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/Member/Auto property 07.fs.bsl b/tests/service/data/SyntaxTree/Member/Auto property 07.fs.bsl index f2be39aed6e..492124d31f0 100644 --- a/tests/service/data/SyntaxTree/Member/Auto property 07.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Auto property 07.fs.bsl @@ -12,7 +12,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None }); AutoProperty @@ -42,7 +42,7 @@ ImplFile (4,4--4,38)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--4,38), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/GetSetMember 01.fs.bsl b/tests/service/data/SyntaxTree/Member/GetSetMember 01.fs.bsl index 3d88c0ff50d..55fb27c87bd 100644 --- a/tests/service/data/SyntaxTree/Member/GetSetMember 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/GetSetMember 01.fs.bsl @@ -12,7 +12,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (3,8--3,10)), None, + (None, [], Const (Unit, (3,8--3,10)), None, PreXmlDoc ((3,8), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,8), { AsKeyword = None }); GetSetMember @@ -194,7 +194,7 @@ ImplFile (4,4--5,92)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (3,8--3,10)), None, + (None, [], Const (Unit, (3,8--3,10)), None, PreXmlDoc ((3,8), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,8), { AsKeyword = None })), (3,5--5,92), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Missing type 01.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Missing type 01.fs.bsl index 028662608dc..d603121ea71 100644 --- a/tests/service/data/SyntaxTree/Member/Implicit ctor - Missing type 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Missing type 01.fs.bsl @@ -14,20 +14,22 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - FromParseError (3,9--3,9), (3,7--3,9))], [], + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + FromParseError (3,9--3,9), (3,7--3,9)), (3,6--3,10)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })], (3,13--3,22)), [], Some (ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - FromParseError (3,9--3,9), (3,7--3,9))], [], + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + FromParseError (3,9--3,9), (3,7--3,9)), (3,6--3,10)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,22), @@ -39,4 +41,4 @@ ImplFile { ConditionalDirectives = [] CodeComments = [] }, set [])) -(3,9)-(3,10) parse error Unexpected symbol ')' in type definition +(3,9)-(3,10) parse error Unexpected symbol ')' in pattern diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Missing type 02.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Missing type 02.fs.bsl index a6f09e6b1ff..d963c4115e8 100644 --- a/tests/service/data/SyntaxTree/Member/Implicit ctor - Missing type 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Missing type 02.fs.bsl @@ -14,23 +14,32 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - FromParseError (3,9--3,9), (3,7--3,9)); - Id (j, None, false, false, false, (3,11--3,12))], - [(3,9--3,10)], (3,6--3,13)), None, + Paren + (Tuple + (false, + [Typed + (Named + (SynIdent (i, None), false, None, + (3,7--3,8)), FromParseError (3,9--3,9), + (3,7--3,9)); + Named + (SynIdent (j, None), false, None, (3,11--3,12))], + [(3,9--3,10)], (3,7--3,12)), (3,6--3,13)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })], (3,16--3,25)), [], Some (ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - FromParseError (3,9--3,9), (3,7--3,9)); - Id (j, None, false, false, false, (3,11--3,12))], - [(3,9--3,10)], (3,6--3,13)), None, + Paren + (Tuple + (false, + [Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + FromParseError (3,9--3,9), (3,7--3,9)); + Named + (SynIdent (j, None), false, None, (3,11--3,12))], + [(3,9--3,10)], (3,7--3,12)), (3,6--3,13)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,25), { LeadingKeyword = Type (3,0--3,4) @@ -41,4 +50,4 @@ ImplFile { ConditionalDirectives = [] CodeComments = [] }, set [])) -(3,9)-(3,10) parse error Unexpected symbol ',' in type definition +(3,9)-(3,10) parse error Unexpected symbol ',' in pattern diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 01.fs b/tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 01.fs new file mode 100644 index 00000000000..29b287b3212 --- /dev/null +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 01.fs @@ -0,0 +1,3 @@ +module Module + +type T(a, (b, c: string), d) = class end diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 01.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 01.fs.bsl new file mode 100644 index 00000000000..2bc4b5f488f --- /dev/null +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 01.fs.bsl @@ -0,0 +1,76 @@ +ImplFile + (ParsedImplFileInput + ("/root/Member/Implicit ctor - Pat - Tuple 01.fs", false, + QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [T], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + ObjectModel + (Class, + [ImplicitCtor + (None, [], + Paren + (Tuple + (false, + [Named + (SynIdent (a, None), false, None, (3,7--3,8)); + Paren + (Tuple + (false, + [Named + (SynIdent (b, None), false, None, + (3,11--3,12)); + Typed + (Named + (SynIdent (c, None), false, None, + (3,14--3,15)), + LongIdent + (SynLongIdent ([string], [], [None])), + (3,14--3,23))], [(3,12--3,13)], + (3,11--3,23)), (3,10--3,24)); + Named + (SynIdent (d, None), false, None, (3,26--3,27))], + [(3,8--3,9); (3,24--3,25)], (3,7--3,27)), + (3,6--3,28)), None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None })], (3,31--3,40)), [], + Some + (ImplicitCtor + (None, [], + Paren + (Tuple + (false, + [Named + (SynIdent (a, None), false, None, (3,7--3,8)); + Paren + (Tuple + (false, + [Named + (SynIdent (b, None), false, None, + (3,11--3,12)); + Typed + (Named + (SynIdent (c, None), false, None, + (3,14--3,15)), + LongIdent + (SynLongIdent ([string], [], [None])), + (3,14--3,23))], [(3,12--3,13)], + (3,11--3,23)), (3,10--3,24)); + Named + (SynIdent (d, None), false, None, (3,26--3,27))], + [(3,8--3,9); (3,24--3,25)], (3,7--3,27)), + (3,6--3,28)), None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None })), (3,5--3,40), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,29--3,30) + WithKeyword = None })], (3,0--3,40))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--3,40), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 02.fs b/tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 02.fs new file mode 100644 index 00000000000..058d241942c --- /dev/null +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 02.fs @@ -0,0 +1,3 @@ +module Module + +type T(a, , c) = class end diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 02.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 02.fs.bsl new file mode 100644 index 00000000000..35502745762 --- /dev/null +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Pat - Tuple 02.fs.bsl @@ -0,0 +1,52 @@ +ImplFile + (ParsedImplFileInput + ("/root/Member/Implicit ctor - Pat - Tuple 02.fs", false, + QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [T], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + ObjectModel + (Class, + [ImplicitCtor + (None, [], + Paren + (Tuple + (false, + [Named + (SynIdent (a, None), false, None, (3,7--3,8)); + Wild (3,10--3,10); + Named + (SynIdent (c, None), false, None, (3,12--3,13))], + [(3,8--3,9); (3,10--3,11)], (3,7--3,13)), + (3,6--3,14)), None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None })], (3,17--3,26)), [], + Some + (ImplicitCtor + (None, [], + Paren + (Tuple + (false, + [Named + (SynIdent (a, None), false, None, (3,7--3,8)); + Wild (3,10--3,10); + Named + (SynIdent (c, None), false, None, (3,12--3,13))], + [(3,8--3,9); (3,10--3,11)], (3,7--3,13)), + (3,6--3,14)), None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None })), (3,5--3,26), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,15--3,16) + WithKeyword = None })], (3,0--3,26))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--3,26), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(3,10)-(3,11) parse error Expecting pattern diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 01.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 01.fs.bsl index 055f0279f10..424a3619305 100644 --- a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 01.fs.bsl @@ -14,27 +14,29 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - Fun - (LongIdent (SynLongIdent ([a], [], [None])), - LongIdent (SynLongIdent ([b], [], [None])), - (3,10--3,16), { ArrowRange = (3,12--3,14) }), - (3,7--3,16))], [], (3,6--3,17)), None, + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + Fun + (LongIdent (SynLongIdent ([a], [], [None])), + LongIdent (SynLongIdent ([b], [], [None])), + (3,10--3,16), { ArrowRange = (3,12--3,14) }), + (3,7--3,16)), (3,6--3,17)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })], (3,20--3,29)), [], Some (ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - Fun - (LongIdent (SynLongIdent ([a], [], [None])), - LongIdent (SynLongIdent ([b], [], [None])), - (3,10--3,16), { ArrowRange = (3,12--3,14) }), - (3,7--3,16))], [], (3,6--3,17)), None, + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + Fun + (LongIdent (SynLongIdent ([a], [], [None])), + LongIdent (SynLongIdent ([b], [], [None])), + (3,10--3,16), { ArrowRange = (3,12--3,14) }), + (3,7--3,16)), (3,6--3,17)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,29), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 02.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 02.fs.bsl index d8fda81fe3e..0146ad5a153 100644 --- a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 02.fs.bsl @@ -14,26 +14,10 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - Fun - (LongIdent (SynLongIdent ([a], [], [None])), - Fun - (LongIdent (SynLongIdent ([b], [], [None])), - LongIdent (SynLongIdent ([c], [], [None])), - (3,15--3,21), - { ArrowRange = (3,17--3,19) }), - (3,10--3,21), { ArrowRange = (3,12--3,14) }), - (3,7--3,21))], [], (3,6--3,22)), None, - PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), - (3,5--3,6), { AsKeyword = None })], (3,25--3,34)), [], - Some - (ImplicitCtor - (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), Fun (LongIdent (SynLongIdent ([a], [], [None])), Fun @@ -41,7 +25,24 @@ ImplFile LongIdent (SynLongIdent ([c], [], [None])), (3,15--3,21), { ArrowRange = (3,17--3,19) }), (3,10--3,21), { ArrowRange = (3,12--3,14) }), - (3,7--3,21))], [], (3,6--3,22)), None, + (3,7--3,21)), (3,6--3,22)), None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None })], (3,25--3,34)), [], + Some + (ImplicitCtor + (None, [], + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + Fun + (LongIdent (SynLongIdent ([a], [], [None])), + Fun + (LongIdent (SynLongIdent ([b], [], [None])), + LongIdent (SynLongIdent ([c], [], [None])), + (3,15--3,21), { ArrowRange = (3,17--3,19) }), + (3,10--3,21), { ArrowRange = (3,12--3,14) }), + (3,7--3,21)), (3,6--3,22)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,34), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 03.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 03.fs.bsl index 5dc98d09cc2..61b3b7f3776 100644 --- a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 03.fs.bsl @@ -14,26 +14,10 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - Fun - (LongIdent (SynLongIdent ([a], [], [None])), - Fun - (LongIdent (SynLongIdent ([b], [], [None])), - LongIdent (SynLongIdent ([c], [], [None])), - (3,15--3,21), - { ArrowRange = (3,17--3,19) }), - (3,10--3,21), { ArrowRange = (3,12--3,14) }), - (3,7--3,21))], [], (3,6--3,22)), None, - PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), - (3,5--3,6), { AsKeyword = None })], (3,25--3,34)), [], - Some - (ImplicitCtor - (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), Fun (LongIdent (SynLongIdent ([a], [], [None])), Fun @@ -41,7 +25,24 @@ ImplFile LongIdent (SynLongIdent ([c], [], [None])), (3,15--3,21), { ArrowRange = (3,17--3,19) }), (3,10--3,21), { ArrowRange = (3,12--3,14) }), - (3,7--3,21))], [], (3,6--3,22)), None, + (3,7--3,21)), (3,6--3,22)), None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None })], (3,25--3,34)), [], + Some + (ImplicitCtor + (None, [], + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + Fun + (LongIdent (SynLongIdent ([a], [], [None])), + Fun + (LongIdent (SynLongIdent ([b], [], [None])), + LongIdent (SynLongIdent ([c], [], [None])), + (3,15--3,21), { ArrowRange = (3,17--3,19) }), + (3,10--3,21), { ArrowRange = (3,12--3,14) }), + (3,7--3,21)), (3,6--3,22)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,34), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 04.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 04.fs.bsl index b230c775e10..ca30a8c2327 100644 --- a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 04.fs.bsl @@ -14,27 +14,29 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - Fun - (LongIdent (SynLongIdent ([a], [], [None])), - FromParseError (3,14--3,14), (3,10--3,14), - { ArrowRange = (3,12--3,14) }), (3,7--3,16))], - [], (3,6--3,16)), None, + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + Fun + (LongIdent (SynLongIdent ([a], [], [None])), + FromParseError (3,14--3,14), (3,10--3,14), + { ArrowRange = (3,12--3,14) }), (3,7--3,16)), + (3,6--3,16)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })], (3,19--3,28)), [], Some (ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - Fun - (LongIdent (SynLongIdent ([a], [], [None])), - FromParseError (3,14--3,14), (3,10--3,14), - { ArrowRange = (3,12--3,14) }), (3,7--3,16))], - [], (3,6--3,16)), None, + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + Fun + (LongIdent (SynLongIdent ([a], [], [None])), + FromParseError (3,14--3,14), (3,10--3,14), + { ArrowRange = (3,12--3,14) }), (3,7--3,16)), + (3,6--3,16)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,28), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 05.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 05.fs.bsl index 00c2967df77..bd89bbaf94e 100644 --- a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 05.fs.bsl @@ -14,26 +14,10 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - Fun - (LongIdent (SynLongIdent ([a], [], [None])), - Fun - (FromParseError (3,15--3,15), - LongIdent (SynLongIdent ([c], [], [None])), - (3,15--3,19), - { ArrowRange = (3,15--3,17) }), - (3,10--3,19), { ArrowRange = (3,12--3,14) }), - (3,7--3,19))], [], (3,6--3,20)), None, - PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), - (3,5--3,6), { AsKeyword = None })], (3,23--3,32)), [], - Some - (ImplicitCtor - (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), Fun (LongIdent (SynLongIdent ([a], [], [None])), Fun @@ -41,7 +25,24 @@ ImplFile LongIdent (SynLongIdent ([c], [], [None])), (3,15--3,19), { ArrowRange = (3,15--3,17) }), (3,10--3,19), { ArrowRange = (3,12--3,14) }), - (3,7--3,19))], [], (3,6--3,20)), None, + (3,7--3,19)), (3,6--3,20)), None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None })], (3,23--3,32)), [], + Some + (ImplicitCtor + (None, [], + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + Fun + (LongIdent (SynLongIdent ([a], [], [None])), + Fun + (FromParseError (3,15--3,15), + LongIdent (SynLongIdent ([c], [], [None])), + (3,15--3,19), { ArrowRange = (3,15--3,17) }), + (3,10--3,19), { ArrowRange = (3,12--3,14) }), + (3,7--3,19)), (3,6--3,20)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,32), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 06.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 06.fs.bsl index 781136aa263..ac58a094acb 100644 --- a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Fun 06.fs.bsl @@ -14,32 +14,10 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - Fun - (LongIdent (SynLongIdent ([a], [], [None])), - Fun - (FromParseError (3,15--3,15), - Tuple - (false, - [Type - (LongIdent - (SynLongIdent ([c], [], [None]))); - Star (3,20--3,21); - Type (FromParseError (3,21--3,21))], - (3,18--3,21)), (3,15--3,21), - { ArrowRange = (3,15--3,17) }), - (3,10--3,21), { ArrowRange = (3,12--3,14) }), - (3,7--3,23))], [], (3,6--3,23)), None, - PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), - (3,5--3,6), { AsKeyword = None })], (3,26--3,35)), [], - Some - (ImplicitCtor - (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), Fun (LongIdent (SynLongIdent ([a], [], [None])), Fun @@ -54,7 +32,31 @@ ImplFile (3,18--3,21)), (3,15--3,21), { ArrowRange = (3,15--3,17) }), (3,10--3,21), { ArrowRange = (3,12--3,14) }), - (3,7--3,23))], [], (3,6--3,23)), None, + (3,7--3,23)), (3,6--3,23)), None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None })], (3,26--3,35)), [], + Some + (ImplicitCtor + (None, [], + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + Fun + (LongIdent (SynLongIdent ([a], [], [None])), + Fun + (FromParseError (3,15--3,15), + Tuple + (false, + [Type + (LongIdent + (SynLongIdent ([c], [], [None]))); + Star (3,20--3,21); + Type (FromParseError (3,21--3,21))], + (3,18--3,21)), (3,15--3,21), + { ArrowRange = (3,15--3,17) }), (3,10--3,21), + { ArrowRange = (3,12--3,14) }), (3,7--3,23)), + (3,6--3,23)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,35), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 01.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 01.fs.bsl index b8315229b80..473bd768b3c 100644 --- a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 01.fs.bsl @@ -14,28 +14,10 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - Tuple - (false, - [Type - (LongIdent - (SynLongIdent ([a], [], [None]))); - Star (3,12--3,13); - Type - (LongIdent - (SynLongIdent ([b], [], [None])))], - (3,10--3,15)), (3,7--3,15))], [], (3,6--3,16)), - None, - PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), - (3,5--3,6), { AsKeyword = None })], (3,19--3,28)), [], - Some - (ImplicitCtor - (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), Tuple (false, [Type @@ -43,8 +25,25 @@ ImplFile Star (3,12--3,13); Type (LongIdent (SynLongIdent ([b], [], [None])))], - (3,10--3,15)), (3,7--3,15))], [], (3,6--3,16)), - None, + (3,10--3,15)), (3,7--3,15)), (3,6--3,16)), + None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None })], (3,19--3,28)), [], + Some + (ImplicitCtor + (None, [], + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + Tuple + (false, + [Type + (LongIdent (SynLongIdent ([a], [], [None]))); + Star (3,12--3,13); + Type + (LongIdent (SynLongIdent ([b], [], [None])))], + (3,10--3,15)), (3,7--3,15)), (3,6--3,16)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,28), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 02.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 02.fs.bsl index 80b2ad46a8d..57b5279161a 100644 --- a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 02.fs.bsl @@ -14,32 +14,10 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - Tuple - (false, - [Type - (LongIdent - (SynLongIdent ([a], [], [None]))); - Star (3,12--3,13); - Type - (LongIdent - (SynLongIdent ([b], [], [None]))); - Star (3,16--3,17); - Type - (LongIdent - (SynLongIdent ([c], [], [None])))], - (3,10--3,19)), (3,7--3,19))], [], (3,6--3,20)), - None, - PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), - (3,5--3,6), { AsKeyword = None })], (3,23--3,32)), [], - Some - (ImplicitCtor - (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), Tuple (false, [Type @@ -50,8 +28,28 @@ ImplFile Star (3,16--3,17); Type (LongIdent (SynLongIdent ([c], [], [None])))], - (3,10--3,19)), (3,7--3,19))], [], (3,6--3,20)), - None, + (3,10--3,19)), (3,7--3,19)), (3,6--3,20)), + None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None })], (3,23--3,32)), [], + Some + (ImplicitCtor + (None, [], + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + Tuple + (false, + [Type + (LongIdent (SynLongIdent ([a], [], [None]))); + Star (3,12--3,13); + Type + (LongIdent (SynLongIdent ([b], [], [None]))); + Star (3,16--3,17); + Type + (LongIdent (SynLongIdent ([c], [], [None])))], + (3,10--3,19)), (3,7--3,19)), (3,6--3,20)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,32), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 03.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 03.fs.bsl index ada1502d243..92b69f0c2b2 100644 --- a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 03.fs.bsl @@ -14,34 +14,34 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - Tuple - (false, - [Type - (LongIdent - (SynLongIdent ([a], [], [None]))); - Star (3,12--3,13); - Type (FromParseError (3,13--3,13))], - (3,10--3,13)), (3,7--3,15))], [], (3,6--3,15)), - None, - PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), - (3,5--3,6), { AsKeyword = None })], (3,18--3,27)), [], - Some - (ImplicitCtor - (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), Tuple (false, [Type (LongIdent (SynLongIdent ([a], [], [None]))); Star (3,12--3,13); Type (FromParseError (3,13--3,13))], - (3,10--3,13)), (3,7--3,15))], [], (3,6--3,15)), - None, + (3,10--3,13)), (3,7--3,15)), (3,6--3,15)), + None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None })], (3,18--3,27)), [], + Some + (ImplicitCtor + (None, [], + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + Tuple + (false, + [Type + (LongIdent (SynLongIdent ([a], [], [None]))); + Star (3,12--3,13); + Type (FromParseError (3,13--3,13))], + (3,10--3,13)), (3,7--3,15)), (3,6--3,15)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,27), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 04.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 04.fs.bsl index e6bbfcbcb71..5ff10cae81b 100644 --- a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 04.fs.bsl @@ -14,30 +14,10 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - Tuple - (false, - [Type - (LongIdent - (SynLongIdent ([a], [], [None]))); - Star (3,12--3,13); - Type - (LongIdent - (SynLongIdent ([b], [], [None]))); - Star (3,16--3,17); - Type (FromParseError (3,17--3,17))], - (3,10--3,17)), (3,7--3,19))], [], (3,6--3,19)), - None, - PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), - (3,5--3,6), { AsKeyword = None })], (3,22--3,31)), [], - Some - (ImplicitCtor - (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), Tuple (false, [Type @@ -47,8 +27,27 @@ ImplFile (LongIdent (SynLongIdent ([b], [], [None]))); Star (3,16--3,17); Type (FromParseError (3,17--3,17))], - (3,10--3,17)), (3,7--3,19))], [], (3,6--3,19)), - None, + (3,10--3,17)), (3,7--3,19)), (3,6--3,19)), + None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None })], (3,22--3,31)), [], + Some + (ImplicitCtor + (None, [], + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + Tuple + (false, + [Type + (LongIdent (SynLongIdent ([a], [], [None]))); + Star (3,12--3,13); + Type + (LongIdent (SynLongIdent ([b], [], [None]))); + Star (3,16--3,17); + Type (FromParseError (3,17--3,17))], + (3,10--3,17)), (3,7--3,19)), (3,6--3,19)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,31), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 05.fs.bsl b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 05.fs.bsl index dfcd368eb5c..a39da9cc29e 100644 --- a/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Implicit ctor - Type - Tuple 05.fs.bsl @@ -14,30 +14,10 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - Tuple - (false, - [Type - (LongIdent - (SynLongIdent ([a], [], [None]))); - Star (3,12--3,13); - Type (FromParseError (3,15--3,15)); - Star (3,14--3,15); - Type - (LongIdent - (SynLongIdent ([c], [], [None])))], - (3,10--3,17)), (3,7--3,17))], [], (3,6--3,19)), - None, - PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), - (3,5--3,6), { AsKeyword = None })], (3,22--3,31)), [], - Some - (ImplicitCtor - (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), Tuple (false, [Type @@ -47,8 +27,27 @@ ImplFile Star (3,14--3,15); Type (LongIdent (SynLongIdent ([c], [], [None])))], - (3,10--3,17)), (3,7--3,17))], [], (3,6--3,19)), - None, + (3,10--3,17)), (3,7--3,17)), (3,6--3,19)), + None, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + (3,5--3,6), { AsKeyword = None })], (3,22--3,31)), [], + Some + (ImplicitCtor + (None, [], + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + Tuple + (false, + [Type + (LongIdent (SynLongIdent ([a], [], [None]))); + Star (3,12--3,13); + Type (FromParseError (3,15--3,15)); + Star (3,14--3,15); + Type + (LongIdent (SynLongIdent ([c], [], [None])))], + (3,10--3,17)), (3,7--3,17)), (3,6--3,19)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,31), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/ImplicitCtorWithAsKeyword.fs.bsl b/tests/service/data/SyntaxTree/Member/ImplicitCtorWithAsKeyword.fs.bsl index 7f97fd1c420..61f182611f8 100644 --- a/tests/service/data/SyntaxTree/Member/ImplicitCtorWithAsKeyword.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/ImplicitCtorWithAsKeyword.fs.bsl @@ -14,58 +14,64 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id - (readAllBytes, None, false, false, false, - (2,33--2,45)), - Fun - (LongIdent - (SynLongIdent ([string], [], [None])), - Array - (1, - LongIdent - (SynLongIdent ([byte], [], [None])), - (2,57--2,63)), (2,47--2,63), - { ArrowRange = (2,54--2,56) }), (2,33--2,63)); - Typed - (Id - (projectOptions, None, false, false, false, - (2,65--2,79)), - LongIdent - (SynLongIdent - ([FSharpProjectOptions], [], [None])), - (2,65--2,101))], [(2,63--2,64)], (2,32--2,102)), - Some this, + Paren + (Tuple + (false, + [Typed + (Named + (SynIdent (readAllBytes, None), false, None, + (2,33--2,45)), + Fun + (LongIdent + (SynLongIdent ([string], [], [None])), + Array + (1, + LongIdent + (SynLongIdent ([byte], [], [None])), + (2,57--2,63)), (2,47--2,63), + { ArrowRange = (2,54--2,56) }), + (2,33--2,63)); + Typed + (Named + (SynIdent (projectOptions, None), false, + None, (2,65--2,79)), + LongIdent + (SynLongIdent + ([FSharpProjectOptions], [], [None])), + (2,65--2,101))], [(2,63--2,64)], + (2,33--2,101)), (2,32--2,102)), Some this, PreXmlDoc ((2,32), FSharp.Compiler.Xml.XmlDocCollector), (2,14--2,32), { AsKeyword = Some (4,4--4,6) })], (8,4--8,13)), [], Some (ImplicitCtor (None, [], - SimplePats - ([Typed - (Id - (readAllBytes, None, false, false, false, - (2,33--2,45)), - Fun - (LongIdent - (SynLongIdent ([string], [], [None])), - Array - (1, - LongIdent - (SynLongIdent ([byte], [], [None])), - (2,57--2,63)), (2,47--2,63), - { ArrowRange = (2,54--2,56) }), (2,33--2,63)); - Typed - (Id - (projectOptions, None, false, false, false, - (2,65--2,79)), - LongIdent - (SynLongIdent - ([FSharpProjectOptions], [], [None])), - (2,65--2,101))], [(2,63--2,64)], (2,32--2,102)), - Some this, + Paren + (Tuple + (false, + [Typed + (Named + (SynIdent (readAllBytes, None), false, None, + (2,33--2,45)), + Fun + (LongIdent + (SynLongIdent ([string], [], [None])), + Array + (1, + LongIdent + (SynLongIdent ([byte], [], [None])), + (2,57--2,63)), (2,47--2,63), + { ArrowRange = (2,54--2,56) }), + (2,33--2,63)); + Typed + (Named + (SynIdent (projectOptions, None), false, + None, (2,65--2,79)), + LongIdent + (SynLongIdent + ([FSharpProjectOptions], [], [None])), + (2,65--2,101))], [(2,63--2,64)], (2,33--2,101)), + (2,32--2,102)), Some this, PreXmlDoc ((2,32), FSharp.Compiler.Xml.XmlDocCollector), (2,14--2,32), { AsKeyword = Some (4,4--4,6) })), (2,5--8,13), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/Member/Member 03.fs.bsl b/tests/service/data/SyntaxTree/Member/Member 03.fs.bsl index 09fde9d81da..cb85a85bfc7 100644 --- a/tests/service/data/SyntaxTree/Member/Member 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Member 03.fs.bsl @@ -66,7 +66,7 @@ ImplFile (SynIdent (this, None), false, None, (5,17--5,21)), None, ArbitraryAfterError ("memberCore1", (5,21--5,21)), - (5,4--6,4), NoneAtInvisible, + (5,4--5,21), NoneAtInvisible, { LeadingKeyword = Member (5,10--5,16) InlineKeyword = None EqualsRange = None }), (5,4--5,21)); diff --git a/tests/service/data/SyntaxTree/Member/Member 07.fs.bsl b/tests/service/data/SyntaxTree/Member/Member 07.fs.bsl index 53fff4c46e5..5e5c51e0f2b 100644 --- a/tests/service/data/SyntaxTree/Member/Member 07.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Member 07.fs.bsl @@ -64,7 +64,7 @@ ImplFile SynArgInfo ([], false, None)), None), Named (SynIdent (this, None), false, None, (5,17--5,21)), - None, Const (Int32 2, (5,25--5,26)), (5,4--5,24), + None, Const (Int32 2, (5,25--5,26)), (5,4--5,21), NoneAtInvisible, { LeadingKeyword = Member (5,10--5,16) InlineKeyword = None diff --git a/tests/service/data/SyntaxTree/Member/Member 12.fs.bsl b/tests/service/data/SyntaxTree/Member/Member 12.fs.bsl index c20d46b6107..94ece410c41 100644 --- a/tests/service/data/SyntaxTree/Member/Member 12.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Member 12.fs.bsl @@ -29,7 +29,7 @@ ImplFile (SynIdent (this, None), false, None, (4,11--4,15)), None, ArbitraryAfterError ("memberCore2", (4,15--4,15)), - (4,11--6,1), NoneAtInvisible, + (4,11--4,15), NoneAtInvisible, { LeadingKeyword = Member (4,4--4,10) InlineKeyword = None EqualsRange = None }), (4,4--4,15))], (4,4--4,15)), diff --git a/tests/service/data/SyntaxTree/Member/Read-onlyPropertyInSynMemberDefnMemberContainsTheRangeOfTheWithKeyword.fs.bsl b/tests/service/data/SyntaxTree/Member/Read-onlyPropertyInSynMemberDefnMemberContainsTheRangeOfTheWithKeyword.fs.bsl index 780fb23542d..6692c520246 100644 --- a/tests/service/data/SyntaxTree/Member/Read-onlyPropertyInSynMemberDefnMemberContainsTheRangeOfTheWithKeyword.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Read-onlyPropertyInSynMemberDefnMemberContainsTheRangeOfTheWithKeyword.fs.bsl @@ -16,7 +16,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (3,8--3,10)), None, + (None, [], Const (Unit, (3,8--3,10)), None, PreXmlDoc ((3,8), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,8), { AsKeyword = None }); GetSetMember @@ -56,7 +56,7 @@ ImplFile SetKeyword = None })], (5,4--5,60)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (3,8--3,10)), None, + (None, [], Const (Unit, (3,8--3,10)), None, PreXmlDoc ((3,8), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,8), { AsKeyword = None })), (3,5--5,60), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/ReadwritePropertyInSynMemberDefnMemberContainsTheRangeOfTheWithKeyword.fs.bsl b/tests/service/data/SyntaxTree/Member/ReadwritePropertyInSynMemberDefnMemberContainsTheRangeOfTheWithKeyword.fs.bsl index a4240a8a27e..8319d790680 100644 --- a/tests/service/data/SyntaxTree/Member/ReadwritePropertyInSynMemberDefnMemberContainsTheRangeOfTheWithKeyword.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/ReadwritePropertyInSynMemberDefnMemberContainsTheRangeOfTheWithKeyword.fs.bsl @@ -17,7 +17,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (2,8--2,10)), None, + (None, [], Const (Unit, (2,8--2,10)), None, PreXmlDoc ((2,8), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,8), { AsKeyword = None }); GetSetMember @@ -92,7 +92,7 @@ ImplFile (4,4--6,50)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (2,8--2,10)), None, + (None, [], Const (Unit, (2,8--2,10)), None, PreXmlDoc ((2,8), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,8), { AsKeyword = None })), (2,5--6,50), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/Member/SynTypeDefnWithAbstractSlotContainsTheRangeOfTheWithKeyword.fs.bsl b/tests/service/data/SyntaxTree/Member/SynTypeDefnWithAbstractSlotContainsTheRangeOfTheWithKeyword.fs.bsl index ea8c1ef757c..f3b24278efa 100644 --- a/tests/service/data/SyntaxTree/Member/SynTypeDefnWithAbstractSlotContainsTheRangeOfTheWithKeyword.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/SynTypeDefnWithAbstractSlotContainsTheRangeOfTheWithKeyword.fs.bsl @@ -16,7 +16,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (2,8--2,10)), None, + (None, [], Const (Unit, (2,8--2,10)), None, PreXmlDoc ((2,8), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,8), { AsKeyword = None }); AbstractSlot @@ -44,7 +44,7 @@ ImplFile (3,4--3,42)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (2,8--2,10)), None, + (None, [], Const (Unit, (2,8--2,10)), None, PreXmlDoc ((2,8), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,8), { AsKeyword = None })), (2,5--3,42), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/Member/SynTypeDefnWithAutoPropertyContainsTheRangeOfTheEqualsSign.fs.bsl b/tests/service/data/SyntaxTree/Member/SynTypeDefnWithAutoPropertyContainsTheRangeOfTheEqualsSign.fs.bsl index e9d5adcfd5b..7cfa4c283eb 100644 --- a/tests/service/data/SyntaxTree/Member/SynTypeDefnWithAutoPropertyContainsTheRangeOfTheEqualsSign.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/SynTypeDefnWithAutoPropertyContainsTheRangeOfTheEqualsSign.fs.bsl @@ -17,18 +17,23 @@ ImplFile (Unspecified, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id - (name, None, false, false, false, (3,12--3,16)), - LongIdent (SynLongIdent ([string], [], [None])), - (3,12--3,25)); - Typed - (Id - (age, None, false, false, false, (3,27--3,30)), - LongIdent (SynLongIdent ([int], [], [None])), - (3,27--3,36))], [(3,25--3,26)], (3,11--3,37)), - None, + Paren + (Tuple + (false, + [Typed + (Named + (SynIdent (name, None), false, None, + (3,12--3,16)), + LongIdent + (SynLongIdent ([string], [], [None])), + (3,12--3,25)); + Typed + (Named + (SynIdent (age, None), false, None, + (3,27--3,30)), + LongIdent (SynLongIdent ([int], [], [None])), + (3,27--3,36))], [(3,25--3,26)], (3,12--3,36)), + (3,11--3,37)), None, PreXmlDoc ((3,11), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,11), { AsKeyword = None }); AutoProperty @@ -57,17 +62,23 @@ ImplFile Some (ImplicitCtor (None, [], - SimplePats - ([Typed - (Id - (name, None, false, false, false, (3,12--3,16)), - LongIdent (SynLongIdent ([string], [], [None])), - (3,12--3,25)); - Typed - (Id (age, None, false, false, false, (3,27--3,30)), - LongIdent (SynLongIdent ([int], [], [None])), - (3,27--3,36))], [(3,25--3,26)], (3,11--3,37)), - None, + Paren + (Tuple + (false, + [Typed + (Named + (SynIdent (name, None), false, None, + (3,12--3,16)), + LongIdent + (SynLongIdent ([string], [], [None])), + (3,12--3,25)); + Typed + (Named + (SynIdent (age, None), false, None, + (3,27--3,30)), + LongIdent (SynLongIdent ([int], [], [None])), + (3,27--3,36))], [(3,25--3,26)], (3,12--3,36)), + (3,11--3,37)), None, PreXmlDoc ((3,11), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,11), { AsKeyword = None })), (2,0--5,40), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Member/SynTypeDefnWithAutoPropertyContainsTheRangeOfTheWithKeyword.fs.bsl b/tests/service/data/SyntaxTree/Member/SynTypeDefnWithAutoPropertyContainsTheRangeOfTheWithKeyword.fs.bsl index 2cbc0581a65..0bef3c32697 100644 --- a/tests/service/data/SyntaxTree/Member/SynTypeDefnWithAutoPropertyContainsTheRangeOfTheWithKeyword.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/SynTypeDefnWithAutoPropertyContainsTheRangeOfTheWithKeyword.fs.bsl @@ -16,7 +16,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (2,8--2,10)), None, + (None, [], Const (Unit, (2,8--2,10)), None, PreXmlDoc ((2,8), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,8), { AsKeyword = None }); AutoProperty @@ -64,7 +64,7 @@ ImplFile GetSetKeywords = None })], (3,4--4,39)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (2,8--2,10)), None, + (None, [], Const (Unit, (2,8--2,10)), None, PreXmlDoc ((2,8), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,8), { AsKeyword = None })), (2,5--4,39), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/Member/SynTypeDefnWithMemberWithSetget.fs.bsl b/tests/service/data/SyntaxTree/Member/SynTypeDefnWithMemberWithSetget.fs.bsl index 85520b1de87..e3fe9618a23 100644 --- a/tests/service/data/SyntaxTree/Member/SynTypeDefnWithMemberWithSetget.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/SynTypeDefnWithMemberWithSetget.fs.bsl @@ -13,7 +13,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None }); GetSetMember @@ -104,7 +104,7 @@ ImplFile (3,4--3,62)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None })), (2,5--3,62), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/Member/Write-onlyPropertyInSynMemberDefnMemberContainsTheRangeOfTheWithKeyword.fs.bsl b/tests/service/data/SyntaxTree/Member/Write-onlyPropertyInSynMemberDefnMemberContainsTheRangeOfTheWithKeyword.fs.bsl index 9dad153789c..79a865c5eed 100644 --- a/tests/service/data/SyntaxTree/Member/Write-onlyPropertyInSynMemberDefnMemberContainsTheRangeOfTheWithKeyword.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Write-onlyPropertyInSynMemberDefnMemberContainsTheRangeOfTheWithKeyword.fs.bsl @@ -16,7 +16,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (3,8--3,10)), None, + (None, [], Const (Unit, (3,8--3,10)), None, PreXmlDoc ((3,8), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,8), { AsKeyword = None }); GetSetMember @@ -63,7 +63,7 @@ ImplFile (5,4--5,79)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (3,8--3,10)), None, + (None, [], Const (Unit, (3,8--3,10)), None, PreXmlDoc ((3,8), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,8), { AsKeyword = None })), (3,5--5,79), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Nullness/AbstractClassProperty.fs.bsl b/tests/service/data/SyntaxTree/Nullness/AbstractClassProperty.fs.bsl index 2bc15f69175..a319c237e5d 100644 --- a/tests/service/data/SyntaxTree/Nullness/AbstractClassProperty.fs.bsl +++ b/tests/service/data/SyntaxTree/Nullness/AbstractClassProperty.fs.bsl @@ -20,7 +20,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (2,17--2,19)), None, + (None, [], Const (Unit, (2,17--2,19)), None, PreXmlDoc ((2,17), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,17), { AsKeyword = None }); AbstractSlot @@ -49,7 +49,7 @@ ImplFile (3,3--3,51)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (2,17--2,19)), None, + (None, [], Const (Unit, (2,17--2,19)), None, PreXmlDoc ((2,17), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,17), { AsKeyword = None })), (1,0--3,51), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/Nullness/SignatureInAbstractMember.fs.bsl b/tests/service/data/SyntaxTree/Nullness/SignatureInAbstractMember.fs.bsl index b7cfdabef4f..f6aca925483 100644 --- a/tests/service/data/SyntaxTree/Nullness/SignatureInAbstractMember.fs.bsl +++ b/tests/service/data/SyntaxTree/Nullness/SignatureInAbstractMember.fs.bsl @@ -13,7 +13,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (1,17--1,19)), None, + (None, [], Const (Unit, (1,17--1,19)), None, PreXmlDoc ((1,17), FSharp.Compiler.Xml.XmlDocCollector), (1,5--1,17), { AsKeyword = None }); AbstractSlot @@ -49,7 +49,7 @@ ImplFile { GetSetKeywords = None })], (2,3--2,61)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (1,17--1,19)), None, + (None, [], Const (Unit, (1,17--1,19)), None, PreXmlDoc ((1,17), FSharp.Compiler.Xml.XmlDocCollector), (1,5--1,17), { AsKeyword = None })), (1,5--2,61), { LeadingKeyword = Type (1,0--1,4) diff --git a/tests/service/data/SyntaxTree/OperatorName/ActivePatternIdentifierInPrivateMember.fs.bsl b/tests/service/data/SyntaxTree/OperatorName/ActivePatternIdentifierInPrivateMember.fs.bsl index f78ea9234b9..a91a973e4e5 100644 --- a/tests/service/data/SyntaxTree/OperatorName/ActivePatternIdentifierInPrivateMember.fs.bsl +++ b/tests/service/data/SyntaxTree/OperatorName/ActivePatternIdentifierInPrivateMember.fs.bsl @@ -13,7 +13,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None }); Member @@ -51,7 +51,7 @@ ImplFile (3,4--7,6)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None })), (2,5--7,6), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/OperatorName/ObjectModelWithTwoMembers.fs.bsl b/tests/service/data/SyntaxTree/OperatorName/ObjectModelWithTwoMembers.fs.bsl index 2679d87a302..760c3f64ca3 100644 --- a/tests/service/data/SyntaxTree/OperatorName/ObjectModelWithTwoMembers.fs.bsl +++ b/tests/service/data/SyntaxTree/OperatorName/ObjectModelWithTwoMembers.fs.bsl @@ -13,7 +13,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None }); LetBindings @@ -103,7 +103,7 @@ ImplFile (3,4--4,79)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (2,6--2,8)), None, + (None, [], Const (Unit, (2,6--2,8)), None, PreXmlDoc ((2,6), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,6), { AsKeyword = None })), (2,5--4,79), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/OperatorName/PartialActivePatternDefinitionWithoutParameters.fs.bsl b/tests/service/data/SyntaxTree/OperatorName/PartialActivePatternDefinitionWithoutParameters.fs.bsl index 62cede07065..d3f6d9d59f8 100644 --- a/tests/service/data/SyntaxTree/OperatorName/PartialActivePatternDefinitionWithoutParameters.fs.bsl +++ b/tests/service/data/SyntaxTree/OperatorName/PartialActivePatternDefinitionWithoutParameters.fs.bsl @@ -21,7 +21,7 @@ ImplFile (false, SynLongIdent ([Boolean; parse], [(2,27--2,28)], [None; None]), None, - (2,20--2,33)), (2,4--2,17), Yes (2,0--2,33), + (2,20--2,33)), (2,5--2,16), Yes (2,0--2,33), { LeadingKeyword = Let (2,0--2,3) InlineKeyword = None EqualsRange = Some (2,18--2,19) })], (2,0--2,33))], diff --git a/tests/service/data/SyntaxTree/Pattern/As 01.fs b/tests/service/data/SyntaxTree/Pattern/As 01.fs new file mode 100644 index 00000000000..9c3786b2552 --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 01.fs @@ -0,0 +1,4 @@ +module Module + +match Some 1 with +| _ as _ -> () diff --git a/tests/service/data/SyntaxTree/Pattern/As 01.fs.bsl b/tests/service/data/SyntaxTree/Pattern/As 01.fs.bsl new file mode 100644 index 00000000000..f0277e7a075 --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 01.fs.bsl @@ -0,0 +1,22 @@ +ImplFile + (ParsedImplFileInput + ("/root/Pattern/As 01.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (Match + (Yes (3,0--3,17), + App + (NonAtomic, false, Ident Some, Const (Int32 1, (3,11--3,12)), + (3,6--3,12)), + [SynMatchClause + (As (Wild (4,2--4,3), Wild (4,7--4,8), (4,2--4,8)), None, + Const (Unit, (4,12--4,14)), (4,2--4,14), Yes, + { ArrowRange = Some (4,9--4,11) + BarRange = Some (4,0--4,1) })], (3,0--4,14), + { MatchKeyword = (3,0--3,5) + WithKeyword = (3,13--3,17) }), (3,0--4,14))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--4,14), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Pattern/As 02.fs b/tests/service/data/SyntaxTree/Pattern/As 02.fs new file mode 100644 index 00000000000..2a098980177 --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 02.fs @@ -0,0 +1,4 @@ +module Module + +match Some 1 with +| _ as -> () diff --git a/tests/service/data/SyntaxTree/Pattern/As 02.fs.bsl b/tests/service/data/SyntaxTree/Pattern/As 02.fs.bsl new file mode 100644 index 00000000000..a39bda6bb7c --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 02.fs.bsl @@ -0,0 +1,24 @@ +ImplFile + (ParsedImplFileInput + ("/root/Pattern/As 02.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (Match + (Yes (3,0--3,17), + App + (NonAtomic, false, Ident Some, Const (Int32 1, (3,11--3,12)), + (3,6--3,12)), + [SynMatchClause + (As (Wild (4,2--4,3), Wild (4,6--4,6), (4,2--4,6)), None, + Const (Unit, (4,10--4,12)), (4,2--4,12), Yes, + { ArrowRange = Some (4,7--4,9) + BarRange = Some (4,0--4,1) })], (3,0--4,12), + { MatchKeyword = (3,0--3,5) + WithKeyword = (3,13--3,17) }), (3,0--4,12))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--4,12), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(4,7)-(4,9) parse error Unexpected symbol '->' in pattern diff --git a/tests/service/data/SyntaxTree/Pattern/As 03.fs b/tests/service/data/SyntaxTree/Pattern/As 03.fs new file mode 100644 index 00000000000..6986fa365c0 --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 03.fs @@ -0,0 +1,3 @@ +module Module + +let _ as _ = () diff --git a/tests/service/data/SyntaxTree/Pattern/As 03.fs.bsl b/tests/service/data/SyntaxTree/Pattern/As 03.fs.bsl new file mode 100644 index 00000000000..87eeb9e821a --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 03.fs.bsl @@ -0,0 +1,21 @@ +ImplFile + (ParsedImplFileInput + ("/root/Pattern/As 03.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + As (Wild (3,4--3,5), Wild (3,9--3,10), (3,4--3,10)), None, + Const (Unit, (3,13--3,15)), (3,4--3,10), Yes (3,0--3,15), + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,11--3,12) })], (3,0--3,15))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--3,15), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Pattern/As 04.fs b/tests/service/data/SyntaxTree/Pattern/As 04.fs new file mode 100644 index 00000000000..9235d0a7966 --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 04.fs @@ -0,0 +1,3 @@ +module Module + +let _ as = () diff --git a/tests/service/data/SyntaxTree/Pattern/As 04.fs.bsl b/tests/service/data/SyntaxTree/Pattern/As 04.fs.bsl new file mode 100644 index 00000000000..dbbdbdd9f3e --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 04.fs.bsl @@ -0,0 +1,23 @@ +ImplFile + (ParsedImplFileInput + ("/root/Pattern/As 04.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + As (Wild (3,4--3,5), Wild (3,8--3,8), (3,4--3,8)), None, + Const (Unit, (3,11--3,13)), (3,4--3,8), Yes (3,0--3,13), + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,9--3,10) })], (3,0--3,13))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--3,13), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(3,6)-(3,8) parse error Expecting pattern diff --git a/tests/service/data/SyntaxTree/Pattern/As 05.fs b/tests/service/data/SyntaxTree/Pattern/As 05.fs new file mode 100644 index 00000000000..66705b3f1a7 --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 05.fs @@ -0,0 +1,4 @@ +module Module + +match Some 1 with +| _ as diff --git a/tests/service/data/SyntaxTree/Pattern/As 05.fs.bsl b/tests/service/data/SyntaxTree/Pattern/As 05.fs.bsl new file mode 100644 index 00000000000..1e26e340c11 --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 05.fs.bsl @@ -0,0 +1,25 @@ +ImplFile + (ParsedImplFileInput + ("/root/Pattern/As 05.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (Match + (Yes (3,0--3,17), + App + (NonAtomic, false, Ident Some, Const (Int32 1, (3,11--3,12)), + (3,6--3,12)), + [SynMatchClause + (As (Wild (4,2--4,3), Wild (4,6--4,6), (4,2--4,6)), None, + ArbitraryAfterError ("patternClauses2", (4,6--4,6)), + (4,2--4,6), Yes, { ArrowRange = None + BarRange = Some (4,0--4,1) })], + (3,0--4,6), { MatchKeyword = (3,0--3,5) + WithKeyword = (3,13--3,17) }), (3,0--4,6))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--4,6), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(5,0)-(5,0) parse error Incomplete structured construct at or before this point in pattern +(3,13)-(3,17) parse error Unexpected end of input in 'match' or 'try' expression diff --git a/tests/service/data/SyntaxTree/Pattern/As 06.fs b/tests/service/data/SyntaxTree/Pattern/As 06.fs new file mode 100644 index 00000000000..e58ff922dbd --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 06.fs @@ -0,0 +1,3 @@ +module Module + +let _ as diff --git a/tests/service/data/SyntaxTree/Pattern/As 06.fs.bsl b/tests/service/data/SyntaxTree/Pattern/As 06.fs.bsl new file mode 100644 index 00000000000..5ce6e55db4d --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 06.fs.bsl @@ -0,0 +1,24 @@ +ImplFile + (ParsedImplFileInput + ("/root/Pattern/As 06.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + As (Wild (3,4--3,5), Wild (3,8--3,8), (3,4--3,8)), None, + ArbitraryAfterError ("localBinding2", (3,8--3,8)), (3,4--3,8), + Yes (3,0--3,8), { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = None })], (3,0--3,8))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--3,8), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(3,6)-(3,8) parse error Expecting pattern +(4,0)-(4,0) parse error Incomplete structured construct at or before this point in binding. Expected '=' or other token. diff --git a/tests/service/data/SyntaxTree/Pattern/As 07.fs b/tests/service/data/SyntaxTree/Pattern/As 07.fs new file mode 100644 index 00000000000..7c22e88390c --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 07.fs @@ -0,0 +1,5 @@ +module Module + +let _ as + +() diff --git a/tests/service/data/SyntaxTree/Pattern/As 07.fs.bsl b/tests/service/data/SyntaxTree/Pattern/As 07.fs.bsl new file mode 100644 index 00000000000..b462b81d90b --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 07.fs.bsl @@ -0,0 +1,25 @@ +ImplFile + (ParsedImplFileInput + ("/root/Pattern/As 07.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + As (Wild (3,4--3,5), Wild (3,8--3,8), (3,4--3,8)), None, + ArbitraryAfterError ("localBinding2", (3,8--3,8)), (3,4--3,8), + Yes (3,0--3,8), { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = None })], (3,0--3,8)); + Expr (Const (Unit, (5,0--5,2)), (5,0--5,2))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--5,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(3,6)-(3,8) parse error Expecting pattern +(5,0)-(5,1) parse error Incomplete structured construct at or before this point in binding. Expected '=' or other token. diff --git a/tests/service/data/SyntaxTree/Pattern/As 08.fs b/tests/service/data/SyntaxTree/Pattern/As 08.fs new file mode 100644 index 00000000000..6dfd373aec5 --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 08.fs @@ -0,0 +1,5 @@ +module Module + +match () with +| _ as +| _ -> () diff --git a/tests/service/data/SyntaxTree/Pattern/As 08.fs.bsl b/tests/service/data/SyntaxTree/Pattern/As 08.fs.bsl new file mode 100644 index 00000000000..48501827087 --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 08.fs.bsl @@ -0,0 +1,23 @@ +ImplFile + (ParsedImplFileInput + ("/root/Pattern/As 08.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (Match + (Yes (3,0--3,13), Const (Unit, (3,6--3,8)), + [SynMatchClause + (Or + (As (Wild (4,2--4,3), Wild (4,6--4,6), (4,2--4,6)), + Wild (5,2--5,3), (4,2--5,3), { BarRange = (5,0--5,1) }), + None, Const (Unit, (5,7--5,9)), (4,2--5,9), Yes, + { ArrowRange = Some (5,4--5,6) + BarRange = Some (4,0--4,1) })], (3,0--5,9), + { MatchKeyword = (3,0--3,5) + WithKeyword = (3,9--3,13) }), (3,0--5,9))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--5,9), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(5,0)-(5,1) parse error Unexpected symbol '|' in pattern diff --git a/tests/service/data/SyntaxTree/Pattern/As 09.fs b/tests/service/data/SyntaxTree/Pattern/As 09.fs new file mode 100644 index 00000000000..21cb82c90e6 --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 09.fs @@ -0,0 +1,5 @@ +module Module + +let _ as + +let _ = () diff --git a/tests/service/data/SyntaxTree/Pattern/As 09.fs.bsl b/tests/service/data/SyntaxTree/Pattern/As 09.fs.bsl new file mode 100644 index 00000000000..ad9aa2247c1 --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 09.fs.bsl @@ -0,0 +1,36 @@ +ImplFile + (ParsedImplFileInput + ("/root/Pattern/As 09.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + As (Wild (3,4--3,5), Wild (3,8--3,8), (3,4--3,8)), None, + ArbitraryAfterError ("localBinding2", (3,8--3,8)), (3,4--3,8), + Yes (3,0--3,8), { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = None })], (3,0--3,8)); + Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((5,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Wild (5,4--5,5), None, Const (Unit, (5,8--5,10)), (5,4--5,5), + Yes (5,0--5,10), { LeadingKeyword = Let (5,0--5,3) + InlineKeyword = None + EqualsRange = Some (5,6--5,7) })], + (5,0--5,10))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--5,10), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(3,6)-(3,8) parse error Expecting pattern +(5,0)-(5,3) parse error Incomplete structured construct at or before this point in binding. Expected '=' or other token. diff --git a/tests/service/data/SyntaxTree/Pattern/As 10.fs b/tests/service/data/SyntaxTree/Pattern/As 10.fs new file mode 100644 index 00000000000..29def47e36b --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 10.fs @@ -0,0 +1,3 @@ +module Module + +let (_ as ) = () diff --git a/tests/service/data/SyntaxTree/Pattern/As 10.fs.bsl b/tests/service/data/SyntaxTree/Pattern/As 10.fs.bsl new file mode 100644 index 00000000000..2b44d412f46 --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 10.fs.bsl @@ -0,0 +1,25 @@ +ImplFile + (ParsedImplFileInput + ("/root/Pattern/As 10.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Paren + (As (Wild (3,5--3,6), Wild (3,9--3,9), (3,5--3,9)), + (3,4--3,11)), None, Const (Unit, (3,14--3,16)), (3,4--3,11), + Yes (3,0--3,16), { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,12--3,13) })], + (3,0--3,16))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--3,16), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(3,10)-(3,11) parse error Unexpected symbol ')' in pattern diff --git a/tests/service/data/SyntaxTree/Pattern/As 11.fs b/tests/service/data/SyntaxTree/Pattern/As 11.fs new file mode 100644 index 00000000000..53c1496b72c --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 11.fs @@ -0,0 +1,3 @@ +module Module + +let 1 as , 3 = () diff --git a/tests/service/data/SyntaxTree/Pattern/As 11.fs.bsl b/tests/service/data/SyntaxTree/Pattern/As 11.fs.bsl new file mode 100644 index 00000000000..84773ba8ee6 --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/As 11.fs.bsl @@ -0,0 +1,28 @@ +ImplFile + (ParsedImplFileInput + ("/root/Pattern/As 11.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Tuple + (false, + [As + (Const (Int32 1, (3,4--3,5)), Wild (3,8--3,8), + (3,4--3,8)); Const (Int32 3, (3,11--3,12))], + [(3,9--3,10)], (3,4--3,12)), None, + Const (Unit, (3,15--3,17)), (3,4--3,12), Yes (3,0--3,17), + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,13--3,14) })], (3,0--3,17))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--3,17), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(3,6)-(3,8) parse error Expecting pattern diff --git a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 01.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 01.fs.bsl index da447d5434b..39999d8f69c 100644 --- a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 01.fs.bsl @@ -17,13 +17,13 @@ ImplFile (FromParseError (3,6--3,6), (3,6--3,6), [], { ColonRange = Some (3,5--3,6) })), Typed - (ArbitraryAfterError ("localBinding2", (5,1--5,1)), - FromParseError (3,6--3,6), (5,1--5,1)), (3,4--3,5), - Yes (3,0--5,1), { LeadingKeyword = Let (3,0--3,3) + (ArbitraryAfterError ("localBinding2", (3,6--3,6)), + FromParseError (3,6--3,6), (3,6--3,6)), (3,4--3,5), + Yes (3,0--3,6), { LeadingKeyword = Let (3,0--3,3) InlineKeyword = None - EqualsRange = None })], (3,0--5,1))], + EqualsRange = None })], (3,0--3,6))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, - (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + (1,0--3,6), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 05.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 05.fs.bsl index 89f2ca602eb..54749497087 100644 --- a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 05.fs.bsl @@ -22,17 +22,18 @@ ImplFile (FromParseError (4,10--4,10), (4,10--4,10), [], { ColonRange = Some (4,9--4,10) })), Typed - (ArbitraryAfterError ("localBinding2", (6,5--6,5)), - FromParseError (4,10--4,10), (6,5--6,5)), - (4,8--4,9), Yes (4,4--6,5), + (ArbitraryAfterError + ("localBinding2", (4,10--4,10)), + FromParseError (4,10--4,10), (4,10--4,10)), + (4,8--4,9), Yes (4,4--4,10), { LeadingKeyword = Let (4,4--4,7) InlineKeyword = None EqualsRange = None })], - ArbitraryAfterError ("seqExpr", (6,5--6,5)), (4,4--6,5), - { InKeyword = None }), (4,4--6,5)), (3,0--6,5)), - (3,0--6,5))], + ArbitraryAfterError ("seqExpr", (4,10--4,10)), + (4,4--4,10), { InKeyword = None }), (4,4--4,10)), + (3,0--4,10)), (3,0--4,10))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, - (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + (1,0--4,10), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SimplePats/SimplePats 02.fs.bsl b/tests/service/data/SyntaxTree/SimplePats/SimplePats 02.fs.bsl index 4a993df804c..fc92f2e4767 100644 --- a/tests/service/data/SyntaxTree/SimplePats/SimplePats 02.fs.bsl +++ b/tests/service/data/SyntaxTree/SimplePats/SimplePats 02.fs.bsl @@ -14,21 +14,23 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - LongIdent (SynLongIdent ([int], [], [None])), - (3,7--3,13))], [], (3,6--3,14)), None, + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + LongIdent (SynLongIdent ([int], [], [None])), + (3,7--3,13)), (3,6--3,14)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })], (3,17--3,26)), [], Some (ImplicitCtor (None, [], - SimplePats - ([Typed - (Id (i, None, false, false, false, (3,7--3,8)), - LongIdent (SynLongIdent ([int], [], [None])), - (3,7--3,13))], [], (3,6--3,14)), None, + Paren + (Typed + (Named + (SynIdent (i, None), false, None, (3,7--3,8)), + LongIdent (SynLongIdent ([int], [], [None])), + (3,7--3,13)), (3,6--3,14)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,26), { LeadingKeyword = Type (3,0--3,4) @@ -44,19 +46,27 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Id (a, None, false, false, false, (4,7--4,8)); - Id (b, None, false, false, false, (4,9--4,10))], - [(4,8--4,9)], (4,6--4,11)), None, + Paren + (Tuple + (false, + [Named + (SynIdent (a, None), false, None, (4,7--4,8)); + Named + (SynIdent (b, None), false, None, (4,9--4,10))], + [(4,8--4,9)], (4,7--4,10)), (4,6--4,11)), None, PreXmlDoc ((4,6), FSharp.Compiler.Xml.XmlDocCollector), (4,5--4,6), { AsKeyword = None })], (4,14--4,23)), [], Some (ImplicitCtor (None, [], - SimplePats - ([Id (a, None, false, false, false, (4,7--4,8)); - Id (b, None, false, false, false, (4,9--4,10))], - [(4,8--4,9)], (4,6--4,11)), None, + Paren + (Tuple + (false, + [Named + (SynIdent (a, None), false, None, (4,7--4,8)); + Named + (SynIdent (b, None), false, None, (4,9--4,10))], + [(4,8--4,9)], (4,7--4,10)), (4,6--4,11)), None, PreXmlDoc ((4,6), FSharp.Compiler.Xml.XmlDocCollector), (4,5--4,6), { AsKeyword = None })), (4,5--4,23), { LeadingKeyword = Type (4,0--4,4) @@ -72,64 +82,73 @@ ImplFile (Class, [ImplicitCtor (None, [], - SimplePats - ([Attrib - (Id - (bar, None, false, false, false, (5,15--5,18)), - [{ Attributes = - [{ TypeName = - SynLongIdent ([Foo], [], [None]) - ArgExpr = Const (Unit, (5,9--5,12)) - Target = None - AppliesToGetterAndSetter = false - Range = (5,9--5,12) }] - Range = (5,7--5,14) }], (5,7--5,18)); - Attrib - (Typed - (Id - (v, None, false, false, false, (5,28--5,29)), - LongIdent (SynLongIdent ([V], [], [None])), - (5,28--5,32)), - [{ Attributes = - [{ TypeName = - SynLongIdent ([Foo], [], [None]) - ArgExpr = Const (Unit, (5,22--5,25)) - Target = None - AppliesToGetterAndSetter = false - Range = (5,22--5,25) }] - Range = (5,20--5,27) }], (5,20--5,32))], - [(5,18--5,19)], (5,6--5,33)), None, + Paren + (Tuple + (false, + [Attrib + (Named + (SynIdent (bar, None), false, None, + (5,15--5,18)), + [{ Attributes = + [{ TypeName = + SynLongIdent ([Foo], [], [None]) + ArgExpr = Const (Unit, (5,9--5,12)) + Target = None + AppliesToGetterAndSetter = false + Range = (5,9--5,12) }] + Range = (5,7--5,14) }], (5,7--5,18)); + Attrib + (Typed + (Named + (SynIdent (v, None), false, None, + (5,28--5,29)), + LongIdent (SynLongIdent ([V], [], [None])), + (5,28--5,32)), + [{ Attributes = + [{ TypeName = + SynLongIdent ([Foo], [], [None]) + ArgExpr = Const (Unit, (5,22--5,25)) + Target = None + AppliesToGetterAndSetter = false + Range = (5,22--5,25) }] + Range = (5,20--5,27) }], (5,20--5,32))], + [(5,18--5,19)], (5,7--5,32)), (5,6--5,33)), None, PreXmlDoc ((5,6), FSharp.Compiler.Xml.XmlDocCollector), (5,5--5,6), { AsKeyword = None })], (5,36--5,45)), [], Some (ImplicitCtor (None, [], - SimplePats - ([Attrib - (Id (bar, None, false, false, false, (5,15--5,18)), - [{ Attributes = - [{ TypeName = - SynLongIdent ([Foo], [], [None]) - ArgExpr = Const (Unit, (5,9--5,12)) - Target = None - AppliesToGetterAndSetter = false - Range = (5,9--5,12) }] - Range = (5,7--5,14) }], (5,7--5,18)); - Attrib - (Typed - (Id - (v, None, false, false, false, (5,28--5,29)), - LongIdent (SynLongIdent ([V], [], [None])), - (5,28--5,32)), - [{ Attributes = - [{ TypeName = - SynLongIdent ([Foo], [], [None]) - ArgExpr = Const (Unit, (5,22--5,25)) - Target = None - AppliesToGetterAndSetter = false - Range = (5,22--5,25) }] - Range = (5,20--5,27) }], (5,20--5,32))], - [(5,18--5,19)], (5,6--5,33)), None, + Paren + (Tuple + (false, + [Attrib + (Named + (SynIdent (bar, None), false, None, + (5,15--5,18)), + [{ Attributes = + [{ TypeName = + SynLongIdent ([Foo], [], [None]) + ArgExpr = Const (Unit, (5,9--5,12)) + Target = None + AppliesToGetterAndSetter = false + Range = (5,9--5,12) }] + Range = (5,7--5,14) }], (5,7--5,18)); + Attrib + (Typed + (Named + (SynIdent (v, None), false, None, + (5,28--5,29)), + LongIdent (SynLongIdent ([V], [], [None])), + (5,28--5,32)), + [{ Attributes = + [{ TypeName = + SynLongIdent ([Foo], [], [None]) + ArgExpr = Const (Unit, (5,22--5,25)) + Target = None + AppliesToGetterAndSetter = false + Range = (5,22--5,25) }] + Range = (5,20--5,27) }], (5,20--5,32))], + [(5,18--5,19)], (5,7--5,32)), (5,6--5,33)), None, PreXmlDoc ((5,6), FSharp.Compiler.Xml.XmlDocCollector), (5,5--5,6), { AsKeyword = None })), (5,5--5,45), { LeadingKeyword = Type (5,0--5,4) @@ -144,12 +163,12 @@ ImplFile ObjectModel (Class, [ImplicitCtor - (None, [], SimplePats ([], [], (6,9--6,11)), None, + (None, [], Const (Unit, (6,9--6,11)), None, PreXmlDoc ((6,9), FSharp.Compiler.Xml.XmlDocCollector), (6,5--6,9), { AsKeyword = None })], (6,14--6,23)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (6,9--6,11)), None, + (None, [], Const (Unit, (6,9--6,11)), None, PreXmlDoc ((6,9), FSharp.Compiler.Xml.XmlDocCollector), (6,5--6,9), { AsKeyword = None })), (6,5--6,23), { LeadingKeyword = Type (6,0--6,4) diff --git a/tests/service/data/SyntaxTree/Type/As 01.fs.bsl b/tests/service/data/SyntaxTree/Type/As 01.fs.bsl index 84f8bb3c3a7..bec2d3a7121 100644 --- a/tests/service/data/SyntaxTree/Type/As 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/As 01.fs.bsl @@ -12,13 +12,13 @@ ImplFile ObjectModel (Class, [ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), Some this, + (None, [], Const (Unit, (3,6--3,8)), Some this, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = Some (3,9--3,11) })], (3,19--3,28)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), Some this, + (None, [], Const (Unit, (3,6--3,8)), Some this, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = Some (3,9--3,11) })), (3,5--3,28), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Type/As 02.fs.bsl b/tests/service/data/SyntaxTree/Type/As 02.fs.bsl index b1a6a433c9c..f40ff1a13d0 100644 --- a/tests/service/data/SyntaxTree/Type/As 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/As 02.fs.bsl @@ -12,13 +12,13 @@ ImplFile ObjectModel (Class, [ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = Some (3,9--3,11) })], (3,14--3,23)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = Some (3,9--3,11) })), (3,5--3,23), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Type/As 05.fs.bsl b/tests/service/data/SyntaxTree/Type/As 05.fs.bsl index 8c216721fbb..52ea9524fef 100644 --- a/tests/service/data/SyntaxTree/Type/As 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/As 05.fs.bsl @@ -11,7 +11,7 @@ ImplFile false, None, (3,5--3,6)), Simple (None (3,5--3,6), (3,5--3,6)), [ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), Some this, + (None, [], Const (Unit, (3,6--3,8)), Some this, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = Some (3,9--3,11) })], None, (3,5--3,6), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Type/As 06.fs.bsl b/tests/service/data/SyntaxTree/Type/As 06.fs.bsl index f7f827efbb1..ed933552272 100644 --- a/tests/service/data/SyntaxTree/Type/As 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/As 06.fs.bsl @@ -11,7 +11,7 @@ ImplFile false, None, (3,5--3,6)), Simple (None (3,5--3,6), (3,5--3,6)), [ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = Some (3,9--3,11) })], None, (3,5--3,6), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Type/As 07.fs.bsl b/tests/service/data/SyntaxTree/Type/As 07.fs.bsl index 59cc29788eb..a491491159b 100644 --- a/tests/service/data/SyntaxTree/Type/As 07.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/As 07.fs.bsl @@ -11,7 +11,7 @@ ImplFile false, None, (3,5--3,6)), Simple (None (3,5--3,6), (3,5--3,6)), [ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), Some this, + (None, [], Const (Unit, (3,6--3,8)), Some this, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = Some (3,9--3,11) })], None, (3,5--3,6), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Type/As 08.fs.bsl b/tests/service/data/SyntaxTree/Type/As 08.fs.bsl index 3894e1a4c18..24254ea6064 100644 --- a/tests/service/data/SyntaxTree/Type/As 08.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/As 08.fs.bsl @@ -11,7 +11,7 @@ ImplFile false, None, (3,5--3,6)), Simple (None (3,5--3,6), (3,5--3,6)), [ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = Some (3,9--3,11) })], None, (3,5--3,6), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Type/Class 03.fs.bsl b/tests/service/data/SyntaxTree/Type/Class 03.fs.bsl index e3e58a8b719..77f8ca8cea0 100644 --- a/tests/service/data/SyntaxTree/Type/Class 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Class 03.fs.bsl @@ -12,12 +12,12 @@ ImplFile ObjectModel (Class, [ImplicitCtor - (None, [], SimplePats ([], [], (3,7--3,9)), None, + (None, [], Const (Unit, (3,7--3,9)), None, PreXmlDoc ((3,7), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })], (4,4--5,7)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (3,7--3,9)), None, + (None, [], Const (Unit, (3,7--3,9)), None, PreXmlDoc ((3,7), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--5,7), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Type/Class 04.fs.bsl b/tests/service/data/SyntaxTree/Type/Class 04.fs.bsl index e137aa4ebfc..80c75b7d5da 100644 --- a/tests/service/data/SyntaxTree/Type/Class 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Class 04.fs.bsl @@ -13,13 +13,13 @@ ImplFile (Class, [ImplicitCtor (Some (Private (3,7--3,14)), [], - SimplePats ([], [], (3,15--3,17)), None, + Const (Unit, (3,15--3,17)), None, PreXmlDoc ((3,7), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })], (4,4--5,7)), [], Some (ImplicitCtor (Some (Private (3,7--3,14)), [], - SimplePats ([], [], (3,15--3,17)), None, + Const (Unit, (3,15--3,17)), None, PreXmlDoc ((3,7), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--5,7), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Type/Class 05.fs.bsl b/tests/service/data/SyntaxTree/Type/Class 05.fs.bsl index 903fa37b286..6516bdc8320 100644 --- a/tests/service/data/SyntaxTree/Type/Class 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Class 05.fs.bsl @@ -19,8 +19,8 @@ ImplFile Target = None AppliesToGetterAndSetter = false Range = (3,9--3,10) }] - Range = (3,7--3,12) }], - SimplePats ([], [], (3,13--3,15)), None, + Range = (3,7--3,12) }], Const (Unit, (3,13--3,15)), + None, PreXmlDoc ((3,7), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })], (4,4--5,7)), [], Some @@ -32,8 +32,8 @@ ImplFile Target = None AppliesToGetterAndSetter = false Range = (3,9--3,10) }] - Range = (3,7--3,12) }], - SimplePats ([], [], (3,13--3,15)), None, + Range = (3,7--3,12) }], Const (Unit, (3,13--3,15)), + None, PreXmlDoc ((3,7), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--5,7), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Type/Enum 01.fs b/tests/service/data/SyntaxTree/Type/Enum 01.fs new file mode 100644 index 00000000000..a860ed5d529 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 01.fs @@ -0,0 +1,6 @@ +module Module + +type E = + | A = 1 + +() diff --git a/tests/service/data/SyntaxTree/Type/Enum 01.fs.bsl b/tests/service/data/SyntaxTree/Type/Enum 01.fs.bsl new file mode 100644 index 00000000000..e10f9194831 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 01.fs.bsl @@ -0,0 +1,28 @@ +ImplFile + (ParsedImplFileInput + ("/root/Type/Enum 01.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [E], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + Simple + (Enum + ([SynEnumCase + ([], SynIdent (A, None), + Const (Int32 1, (4,10--4,11)), + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + (4,6--4,11), { BarRange = Some (4,4--4,5) + EqualsRange = (4,8--4,9) })], + (4,4--4,11)), (4,4--4,11)), [], None, (3,5--4,11), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,7--3,8) + WithKeyword = None })], (3,0--4,11)); + Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Type/Enum 02.fs b/tests/service/data/SyntaxTree/Type/Enum 02.fs new file mode 100644 index 00000000000..9249fabeb7e --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 02.fs @@ -0,0 +1,6 @@ +module Module + +type E = + A = 1 + +() diff --git a/tests/service/data/SyntaxTree/Type/Enum 02.fs.bsl b/tests/service/data/SyntaxTree/Type/Enum 02.fs.bsl new file mode 100644 index 00000000000..e586e137997 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 02.fs.bsl @@ -0,0 +1,27 @@ +ImplFile + (ParsedImplFileInput + ("/root/Type/Enum 02.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [E], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + Simple + (Enum + ([SynEnumCase + ([], SynIdent (A, None), Const (Int32 1, (4,8--4,9)), + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + (4,4--4,9), { BarRange = None + EqualsRange = (4,6--4,7) })], + (4,4--4,9)), (4,4--4,9)), [], None, (3,5--4,9), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,7--3,8) + WithKeyword = None })], (3,0--4,9)); + Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Type/Enum 03.fs b/tests/service/data/SyntaxTree/Type/Enum 03.fs new file mode 100644 index 00000000000..4824f909c87 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 03.fs @@ -0,0 +1,6 @@ +module Module + +type E = + | A = + +() diff --git a/tests/service/data/SyntaxTree/Type/Enum 03.fs.bsl b/tests/service/data/SyntaxTree/Type/Enum 03.fs.bsl new file mode 100644 index 00000000000..17ed2baa172 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 03.fs.bsl @@ -0,0 +1,31 @@ +ImplFile + (ParsedImplFileInput + ("/root/Type/Enum 03.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [E], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + Simple + (Enum + ([SynEnumCase + ([], SynIdent (A, None), + ArbitraryAfterError + ("attrUnionCaseDecl", (4,9--4,9)), + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + (4,6--4,9), { BarRange = Some (4,4--4,5) + EqualsRange = (4,8--4,9) })], + (4,4--4,9)), (4,4--4,9)), [], None, (3,5--4,9), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,7--3,8) + WithKeyword = None })], (3,0--4,9)); + Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(6,0)-(6,1) parse error Incomplete structured construct at or before this point in union case diff --git a/tests/service/data/SyntaxTree/Type/Enum 04.fs b/tests/service/data/SyntaxTree/Type/Enum 04.fs new file mode 100644 index 00000000000..98244e15ee3 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 04.fs @@ -0,0 +1,7 @@ +module Module + +type E = + | A = + | B = 2 + +() diff --git a/tests/service/data/SyntaxTree/Type/Enum 04.fs.bsl b/tests/service/data/SyntaxTree/Type/Enum 04.fs.bsl new file mode 100644 index 00000000000..faed14098e3 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 04.fs.bsl @@ -0,0 +1,37 @@ +ImplFile + (ParsedImplFileInput + ("/root/Type/Enum 04.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [E], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + Simple + (Enum + ([SynEnumCase + ([], SynIdent (A, None), + ArbitraryAfterError + ("attrUnionCaseDecl", (4,9--4,9)), + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + (4,6--4,9), { BarRange = Some (4,4--4,5) + EqualsRange = (4,8--4,9) }); + SynEnumCase + ([], SynIdent (B, None), + Const (Int32 2, (5,10--5,11)), + PreXmlDoc ((5,4), FSharp.Compiler.Xml.XmlDocCollector), + (5,6--5,11), { BarRange = Some (5,4--5,5) + EqualsRange = (5,8--5,9) })], + (4,4--5,11)), (4,4--5,11)), [], None, (3,5--5,11), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,7--3,8) + WithKeyword = None })], (3,0--5,11)); + Expr (Const (Unit, (7,0--7,2)), (7,0--7,2))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(5,4)-(5,5) parse error Unexpected symbol '|' in union case diff --git a/tests/service/data/SyntaxTree/Type/Enum 05.fs b/tests/service/data/SyntaxTree/Type/Enum 05.fs new file mode 100644 index 00000000000..191e3b2f926 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 05.fs @@ -0,0 +1,6 @@ +module Module + +type E = + A = + +() diff --git a/tests/service/data/SyntaxTree/Type/Enum 05.fs.bsl b/tests/service/data/SyntaxTree/Type/Enum 05.fs.bsl new file mode 100644 index 00000000000..fd808927027 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 05.fs.bsl @@ -0,0 +1,31 @@ +ImplFile + (ParsedImplFileInput + ("/root/Type/Enum 05.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [E], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + Simple + (Enum + ([SynEnumCase + ([], SynIdent (A, None), + ArbitraryAfterError + ("firstUnionCaseDecl", (4,7--4,7)), + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + (4,4--4,7), { BarRange = None + EqualsRange = (4,6--4,7) })], + (4,4--4,7)), (4,4--4,7)), [], None, (3,5--4,7), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,7--3,8) + WithKeyword = None })], (3,0--4,7)); + Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(6,0)-(6,1) parse error Incomplete structured construct at or before this point in type definition diff --git a/tests/service/data/SyntaxTree/Type/Enum 06.fs b/tests/service/data/SyntaxTree/Type/Enum 06.fs new file mode 100644 index 00000000000..5c2fb93e2b1 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 06.fs @@ -0,0 +1,7 @@ +module Module + +type E = + A = + | B = 2 + +() diff --git a/tests/service/data/SyntaxTree/Type/Enum 06.fs.bsl b/tests/service/data/SyntaxTree/Type/Enum 06.fs.bsl new file mode 100644 index 00000000000..b7fd06cbbd2 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 06.fs.bsl @@ -0,0 +1,37 @@ +ImplFile + (ParsedImplFileInput + ("/root/Type/Enum 06.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [E], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + Simple + (Enum + ([SynEnumCase + ([], SynIdent (A, None), + ArbitraryAfterError + ("firstUnionCaseDeclOfMany1", (4,9--4,9)), + PreXmlDoc ((4,6), FSharp.Compiler.Xml.XmlDocCollector), + (4,6--4,9), { BarRange = None + EqualsRange = (4,8--4,9) }); + SynEnumCase + ([], SynIdent (B, None), + Const (Int32 2, (5,10--5,11)), + PreXmlDoc ((5,4), FSharp.Compiler.Xml.XmlDocCollector), + (5,6--5,11), { BarRange = Some (5,4--5,5) + EqualsRange = (5,8--5,9) })], + (4,6--5,11)), (4,6--5,11)), [], None, (3,5--5,11), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,7--3,8) + WithKeyword = None })], (3,0--5,11)); + Expr (Const (Unit, (7,0--7,2)), (7,0--7,2))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(5,4)-(5,5) parse error Unexpected symbol '|' in type definition diff --git a/tests/service/data/SyntaxTree/Type/Enum 07 - Eof.fs b/tests/service/data/SyntaxTree/Type/Enum 07 - Eof.fs new file mode 100644 index 00000000000..87cd5255650 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 07 - Eof.fs @@ -0,0 +1,4 @@ +module Module + +type E = + | A = diff --git a/tests/service/data/SyntaxTree/Type/Enum 07 - Eof.fs.bsl b/tests/service/data/SyntaxTree/Type/Enum 07 - Eof.fs.bsl new file mode 100644 index 00000000000..5278e60ecd8 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 07 - Eof.fs.bsl @@ -0,0 +1,30 @@ +ImplFile + (ParsedImplFileInput + ("/root/Type/Enum 07 - Eof.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [E], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + Simple + (Enum + ([SynEnumCase + ([], SynIdent (A, None), + ArbitraryAfterError + ("attrUnionCaseDecl", (4,9--4,9)), + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + (4,6--4,9), { BarRange = Some (4,4--4,5) + EqualsRange = (4,8--4,9) })], + (4,4--4,9)), (4,4--4,9)), [], None, (3,5--4,9), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,7--3,8) + WithKeyword = None })], (3,0--4,9))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--4,9), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(5,0)-(5,0) parse error Incomplete structured construct at or before this point in union case diff --git a/tests/service/data/SyntaxTree/Type/Enum 08 - Eof.fs b/tests/service/data/SyntaxTree/Type/Enum 08 - Eof.fs new file mode 100644 index 00000000000..e66175c3823 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 08 - Eof.fs @@ -0,0 +1,4 @@ +module Module + +type E = + A = diff --git a/tests/service/data/SyntaxTree/Type/Enum 08 - Eof.fs.bsl b/tests/service/data/SyntaxTree/Type/Enum 08 - Eof.fs.bsl new file mode 100644 index 00000000000..b715aa57067 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 08 - Eof.fs.bsl @@ -0,0 +1,30 @@ +ImplFile + (ParsedImplFileInput + ("/root/Type/Enum 08 - Eof.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [E], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + Simple + (Enum + ([SynEnumCase + ([], SynIdent (A, None), + ArbitraryAfterError + ("firstUnionCaseDecl", (4,7--4,7)), + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + (4,4--4,7), { BarRange = None + EqualsRange = (4,6--4,7) })], + (4,4--4,7)), (4,4--4,7)), [], None, (3,5--4,7), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,7--3,8) + WithKeyword = None })], (3,0--4,7))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--4,7), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(5,0)-(5,0) parse error Incomplete structured construct at or before this point in type definition diff --git a/tests/service/data/SyntaxTree/Type/Enum 09 - Eof.fs b/tests/service/data/SyntaxTree/Type/Enum 09 - Eof.fs new file mode 100644 index 00000000000..cb185c00cd5 --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 09 - Eof.fs @@ -0,0 +1,4 @@ +module Module + +type E = + | A = \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/Type/Enum 09 - Eof.fs.bsl b/tests/service/data/SyntaxTree/Type/Enum 09 - Eof.fs.bsl new file mode 100644 index 00000000000..c1756aeb77a --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 09 - Eof.fs.bsl @@ -0,0 +1,30 @@ +ImplFile + (ParsedImplFileInput + ("/root/Type/Enum 09 - Eof.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [E], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + Simple + (Enum + ([SynEnumCase + ([], SynIdent (A, None), + ArbitraryAfterError + ("attrUnionCaseDecl", (4,9--4,9)), + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + (4,6--4,9), { BarRange = Some (4,4--4,5) + EqualsRange = (4,8--4,9) })], + (4,4--4,9)), (4,4--4,9)), [], None, (3,5--4,9), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,7--3,8) + WithKeyword = None })], (3,0--4,9))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--4,9), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(4,0)-(4,9) parse error Incomplete structured construct at or before this point in union case diff --git a/tests/service/data/SyntaxTree/Type/Enum 10 - Eof.fs b/tests/service/data/SyntaxTree/Type/Enum 10 - Eof.fs new file mode 100644 index 00000000000..0f08891b10e --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 10 - Eof.fs @@ -0,0 +1,4 @@ +module Module + +type E = + A = \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/Type/Enum 10 - Eof.fs.bsl b/tests/service/data/SyntaxTree/Type/Enum 10 - Eof.fs.bsl new file mode 100644 index 00000000000..6a6bf175b1d --- /dev/null +++ b/tests/service/data/SyntaxTree/Type/Enum 10 - Eof.fs.bsl @@ -0,0 +1,30 @@ +ImplFile + (ParsedImplFileInput + ("/root/Type/Enum 10 - Eof.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [E], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + Simple + (Enum + ([SynEnumCase + ([], SynIdent (A, None), + ArbitraryAfterError + ("firstUnionCaseDecl", (4,7--4,7)), + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + (4,4--4,7), { BarRange = None + EqualsRange = (4,6--4,7) })], + (4,4--4,7)), (4,4--4,7)), [], None, (3,5--4,7), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,7--3,8) + WithKeyword = None })], (3,0--4,7))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--4,7), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(4,0)-(4,7) parse error Incomplete structured construct at or before this point in type definition diff --git a/tests/service/data/SyntaxTree/Type/Primary ctor 01.fs.bsl b/tests/service/data/SyntaxTree/Type/Primary ctor 01.fs.bsl index 24fbd4e7c8f..6717cb55b41 100644 --- a/tests/service/data/SyntaxTree/Type/Primary ctor 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Primary ctor 01.fs.bsl @@ -12,12 +12,12 @@ ImplFile ObjectModel (Class, [ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })], (3,11--3,20)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,20), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Type/Primary ctor 02.fs.bsl b/tests/service/data/SyntaxTree/Type/Primary ctor 02.fs.bsl index a770ed3442e..fbb48e2fd0a 100644 --- a/tests/service/data/SyntaxTree/Type/Primary ctor 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Primary ctor 02.fs.bsl @@ -12,12 +12,12 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })], (3,5--3,10)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,10), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Type/Primary ctor 03.fs.bsl b/tests/service/data/SyntaxTree/Type/Primary ctor 03.fs.bsl index 882320fe29f..7bf4dedee58 100644 --- a/tests/service/data/SyntaxTree/Type/Primary ctor 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Primary ctor 03.fs.bsl @@ -11,7 +11,7 @@ ImplFile false, None, (3,5--3,6)), Simple (None (3,5--3,6), (3,5--3,6)), [ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })], None, (3,5--3,6), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Type/Primary ctor 04.fs.bsl b/tests/service/data/SyntaxTree/Type/Primary ctor 04.fs.bsl index 6505497c378..a46c198cdfe 100644 --- a/tests/service/data/SyntaxTree/Type/Primary ctor 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Primary ctor 04.fs.bsl @@ -12,12 +12,12 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })], (3,5--3,10)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,10), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Type/Primary ctor 05.fs.bsl b/tests/service/data/SyntaxTree/Type/Primary ctor 05.fs.bsl index 352346a2396..17215f552fc 100644 --- a/tests/service/data/SyntaxTree/Type/Primary ctor 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Primary ctor 05.fs.bsl @@ -11,7 +11,7 @@ ImplFile false, None, (3,5--3,6)), Simple (None (3,5--3,6), (3,5--3,6)), [ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })], None, (3,5--3,6), { LeadingKeyword = Type (3,0--3,4) diff --git a/tests/service/data/SyntaxTree/Type/SynMemberDefnInterfaceContainsTheRangeOfTheWithKeyword.fs.bsl b/tests/service/data/SyntaxTree/Type/SynMemberDefnInterfaceContainsTheRangeOfTheWithKeyword.fs.bsl index ed20d359009..cc2e1a3997f 100644 --- a/tests/service/data/SyntaxTree/Type/SynMemberDefnInterfaceContainsTheRangeOfTheWithKeyword.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/SynMemberDefnInterfaceContainsTheRangeOfTheWithKeyword.fs.bsl @@ -16,7 +16,7 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (2,8--2,10)), None, + (None, [], Const (Unit, (2,8--2,10)), None, PreXmlDoc ((2,8), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,8), { AsKeyword = None }); Interface @@ -57,7 +57,7 @@ ImplFile None, (5,4--5,19))], (3,4--5,19)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (2,8--2,10)), None, + (None, [], Const (Unit, (2,8--2,10)), None, PreXmlDoc ((2,8), FSharp.Compiler.Xml.XmlDocCollector), (2,5--2,8), { AsKeyword = None })), (2,5--5,19), { LeadingKeyword = Type (2,0--2,4) diff --git a/tests/service/data/SyntaxTree/Type/Type 11.fs.bsl b/tests/service/data/SyntaxTree/Type/Type 11.fs.bsl index fb9f7a3d57e..074cead59e8 100644 --- a/tests/service/data/SyntaxTree/Type/Type 11.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Type 11.fs.bsl @@ -12,12 +12,12 @@ ImplFile ObjectModel (Unspecified, [ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })], (3,5--3,10)), [], Some (ImplicitCtor - (None, [], SimplePats ([], [], (3,6--3,8)), None, + (None, [], Const (Unit, (3,6--3,8)), None, PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), (3,5--3,6), { AsKeyword = None })), (3,5--3,10), { LeadingKeyword = Type (3,0--3,4) diff --git a/vsintegration/readme.md b/vsintegration/readme.md index 4f929238bdc..b09865b8149 100644 --- a/vsintegration/readme.md +++ b/vsintegration/readme.md @@ -12,6 +12,10 @@ Top-level project for the Visual F# IDE tools. This project contains the follow In general, if something is implemented here and the logic becomes rather lengthy, it may be a good idea to push that logic down into the F# Compiler Service so that other editors can benefit. +# src/FSharp.VS.FSI + +F# Interactive implementation. + # src/FSharp.UIResources GUI controls and resources for Visual F# tooling. diff --git a/vsintegration/src/FSharp.Editor/Common/CancellableTasks.fs b/vsintegration/src/FSharp.Editor/Common/CancellableTasks.fs index 1cd71d4228e..0326688f987 100644 --- a/vsintegration/src/FSharp.Editor/Common/CancellableTasks.fs +++ b/vsintegration/src/FSharp.Editor/Common/CancellableTasks.fs @@ -1107,6 +1107,16 @@ module CancellableTasks = return! Task.WhenAll (tasks) } + let inline sequential (tasks: CancellableTask<'a> seq) = + cancellableTask { + let! ct = getCancellationToken () + let results = ResizeArray() + for task in tasks do + let! result = start ct task + results.Add(result) + return results + } + let inline ignore ([] ctask: CancellableTask<_>) = toUnit ctask /// diff --git a/vsintegration/src/FSharp.Editor/Common/Extensions.fs b/vsintegration/src/FSharp.Editor/Common/Extensions.fs index eb2f61c4147..b0eb7305713 100644 --- a/vsintegration/src/FSharp.Editor/Common/Extensions.fs +++ b/vsintegration/src/FSharp.Editor/Common/Extensions.fs @@ -87,7 +87,7 @@ module private SourceText = let combineValues (values: seq<'T>) = (0, values) ||> Seq.fold (fun hash value -> combine (value.GetHashCode()) hash) - let weakTable = ConditionalWeakTable() + let weakTable = ConditionalWeakTable() let create (sourceText: SourceText) = let sourceText = @@ -111,7 +111,9 @@ module private SourceText = |> Hash.combine encodingHash |> Hash.combine contentsHash |> Hash.combine sourceText.Length - interface ISourceText with + + override _.ToString() = sourceText.ToString() + interface ISourceTextNew with member _.Item with get index = sourceText.[index] @@ -197,6 +199,8 @@ module private SourceText = let lastLine = this.GetLineString(range.EndLine - 1) sb.Append(lastLine.Substring(0, range.EndColumn)).ToString() + + member _.GetChecksum() = sourceText.GetChecksum() } sourceText diff --git a/vsintegration/src/FSharp.Editor/Common/Logging.fs b/vsintegration/src/FSharp.Editor/Common/Logging.fs index 0ba681dc589..a69779e9acc 100644 --- a/vsintegration/src/FSharp.Editor/Common/Logging.fs +++ b/vsintegration/src/FSharp.Editor/Common/Logging.fs @@ -93,7 +93,10 @@ module Logging = let inline debug msg = Printf.kprintf Debug.WriteLine msg let private logger = lazy Logger(Logger.GlobalServiceProvider) - let private log logType msg = logger.Value.Log(logType, msg) + + let private log logType msg = + logger.Value.Log(logType, msg) + System.Diagnostics.Trace.TraceInformation(msg) let logMsg msg = log LogType.Message msg let logInfo msg = log LogType.Info msg diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs index 0014f1d2397..a18987ac48c 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs @@ -26,7 +26,12 @@ open CancellableTasks module Logger = Microsoft.VisualStudio.FSharp.Editor.Logger type internal FSharpCompletionProvider - (workspace: Workspace, serviceProvider: SVsServiceProvider, assemblyContentProvider: AssemblyContentProvider) = + ( + workspace: Workspace, + serviceProvider: SVsServiceProvider, + assemblyContentProvider: AssemblyContentProvider, + editorOptions: EditorOptions + ) = inherit FSharpCompletionProviderBase() @@ -380,7 +385,16 @@ type internal FSharpCompletionProvider let documentation = List() let collector = RoslynHelpers.CollectTaggedText documentation // mix main description and xmldoc by using one collector - XmlDocumentation.BuildDataTipText(documentationBuilder, collector, collector, collector, collector, collector, description) + XmlDocumentation.BuildDataTipText( + documentationBuilder, + collector, + collector, + collector, + collector, + collector, + description, + editorOptions.QuickInfo.ShowRemarks + ) Task.FromResult(CompletionDescription.Create(documentation.ToImmutableArray())) | _ -> diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs index 7975b31b155..13f7e3d3b30 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs @@ -24,7 +24,7 @@ type internal FSharpCompletionService let builtInProviders = ImmutableArray.Create( - FSharpCompletionProvider(workspace, serviceProvider, assemblyContentProvider), + FSharpCompletionProvider(workspace, serviceProvider, assemblyContentProvider, settings), FSharpCommonCompletionProvider.Create(HashDirectiveCompletionProvider.Create(workspace, projectInfoManager)) ) diff --git a/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs b/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs index 595f051900b..f00deaa9250 100644 --- a/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs +++ b/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs @@ -58,7 +58,7 @@ type SignatureHelpData = [] [)>] -type internal FSharpSignatureHelpProvider [] (serviceProvider: SVsServiceProvider) = +type internal FSharpSignatureHelpProvider [] (serviceProvider: SVsServiceProvider, editorOptions: EditorOptions) = let documentationBuilder = XmlDocumentation.CreateDocumentationBuilder(serviceProvider.XMLMemberIndexService) @@ -79,7 +79,8 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi documentationBuilder: IDocumentationBuilder, sourceText: SourceText, caretPosition: int, - triggerIsTypedChar: char option + triggerIsTypedChar: char option, + editorOptions: EditorOptions ) = asyncMaybe { let textLines = sourceText.Lines @@ -206,7 +207,8 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi RoslynHelpers.CollectTaggedText mainDescription, RoslynHelpers.CollectTaggedText documentation, method.Description, - false + false, + editorOptions.QuickInfo.ShowRemarks ) let parameters = @@ -225,7 +227,8 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi documentationBuilder, RoslynHelpers.CollectTaggedText doc, method.XmlDoc, - p.ParameterName + p.ParameterName, + editorOptions.QuickInfo.ShowRemarks ) p.Display |> Seq.iter (RoslynHelpers.CollectTaggedText parts) @@ -292,7 +295,8 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi sourceText: SourceText, caretPosition: int, adjustedColumnInSource: int, - filePath: string + filePath: string, + editorOptions: EditorOptions ) = asyncMaybe { let textLine = sourceText.Lines.GetLineFromPosition(adjustedColumnInSource) @@ -430,7 +434,8 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi typeParameterMap.Add, usage.Add, exceptions.Add, - tooltip + tooltip, + editorOptions.QuickInfo.ShowRemarks ) let fsharpDocs = @@ -606,7 +611,8 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi documentationBuilder: IDocumentationBuilder, caretPosition: int, triggerTypedChar: char option, - possibleCurrentSignatureHelpSessionKind: CurrentSignatureHelpSessionKind option + possibleCurrentSignatureHelpSessionKind: CurrentSignatureHelpSessionKind option, + editorOptions: EditorOptions ) = asyncMaybe { @@ -623,14 +629,18 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi let caretLineColumn = caretLinePos.Character let adjustedColumnInSource = - - let rec loop ch pos = - if Char.IsWhiteSpace(ch) then - loop sourceText.[pos - 1] (pos - 1) - else + let rec loop pos = + if pos = 0 then pos + else + let nextPos = pos - 1 + + if not (Char.IsWhiteSpace sourceText[nextPos]) then + pos + else + loop nextPos - loop sourceText.[caretPosition - 1] (caretPosition - 1) + loop (caretPosition - 1) let adjustedColumnChar = sourceText.[adjustedColumnInSource] @@ -655,7 +665,8 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi sourceText, caretPosition, adjustedColumnInSource, - document.FilePath + document.FilePath, + editorOptions ) | _, Some FunctionApplication when adjustedColumnChar <> ',' @@ -674,7 +685,8 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi sourceText, caretPosition, adjustedColumnInSource, - document.FilePath + document.FilePath, + editorOptions ) | _ -> let! paramInfoLocations = parseResults.FindParameterLocations(Position.fromZ caretLinePos.Line caretLineColumn) @@ -688,7 +700,8 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi documentationBuilder, sourceText, caretPosition, - triggerTypedChar + triggerTypedChar, + editorOptions ) } @@ -722,7 +735,8 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi documentationBuilder, position, triggerTypedChar, - possibleCurrentSignatureHelpSessionKind + possibleCurrentSignatureHelpSessionKind, + editorOptions ) match signatureHelpDataOpt with diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/UnnecessaryParenthesesDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/UnnecessaryParenthesesDiagnosticAnalyzer.fs index bc433015ec9..07201f8a0a3 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/UnnecessaryParenthesesDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/UnnecessaryParenthesesDiagnosticAnalyzer.fs @@ -3,11 +3,12 @@ namespace Microsoft.VisualStudio.FSharp.Editor open System.Composition +open System.Collections.Generic open System.Collections.Immutable open System.Runtime.Caching open System.Threading open System.Threading.Tasks -open FSharp.Compiler.EditorServices +open FSharp.Compiler.Syntax open FSharp.Compiler.Text open Microsoft.CodeAnalysis open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Diagnostics @@ -70,13 +71,31 @@ type internal UnnecessaryParenthesesDiagnosticAnalyzer [] let getLineString line = sourceText.Lines[Line.toZ line].ToString() - let! unnecessaryParentheses = UnnecessaryParentheses.getUnnecessaryParentheses getLineString parseResults.ParseTree + let unnecessaryParentheses = + (HashSet Range.comparer, parseResults.ParseTree) + ||> ParsedInput.fold (fun ranges path node -> + match node with + | SyntaxNode.SynExpr(SynExpr.Paren(expr = inner; rightParenRange = Some _; range = range)) when + not (SynExpr.shouldBeParenthesizedInContext getLineString path inner) + -> + ignore (ranges.Add range) + ranges + + | SyntaxNode.SynPat(SynPat.Paren(inner, range)) when not (SynPat.shouldBeParenthesizedInContext path inner) -> + ignore (ranges.Add range) + ranges + + | _ -> ranges) let diagnostics = - unnecessaryParentheses - |> Seq.map (fun range -> - Diagnostic.Create(descriptor, RoslynHelpers.RangeToLocation(range, sourceText, document.FilePath))) - |> Seq.toImmutableArray + let builder = ImmutableArray.CreateBuilder unnecessaryParentheses.Count + + for range in unnecessaryParentheses do + builder.Add( + Diagnostic.Create(descriptor, RoslynHelpers.RangeToLocation(range, sourceText, document.FilePath)) + ) + + builder.MoveToImmutable() ignore (cache.Remove key) diff --git a/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs b/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs index 1c807bfad91..b3228180ff2 100644 --- a/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs +++ b/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs @@ -100,6 +100,7 @@ type internal IDocumentationBuilder = processedXml: string * showExceptions: bool * showParameters: bool * + showRemarks: bool * paramName: string option -> unit @@ -111,6 +112,7 @@ type internal IDocumentationBuilder = signature: string * showExceptions: bool * showParameters: bool * + showRemarks: bool * paramName: string option -> unit @@ -165,6 +167,7 @@ module internal XmlDocumentation = | "typeref" -> for attr in el.Attributes() do WriteAttribute collector attr "name" (tagParameter >> collector.Add) + | "br" -> AppendHardLine collector | _ -> WriteNodes collector (el.Nodes()) | _ -> () @@ -210,13 +213,34 @@ module internal XmlDocumentation = with _ -> None - member _.CollectSummary(collector: ITaggedTextCollector) = + member _.CollectSummary(collector: ITaggedTextCollector, showRemarks) = match Seq.tryHead (doc.Descendants(XName.op_Implicit "summary")) with | None -> () | Some el -> EnsureHardLine collector WriteElement collector el + match Seq.tryHead (doc.Descendants(XName.op_Implicit "returns")) with + | None -> () + | Some el -> + AppendHardLine collector + AppendHardLine collector + AppendOnNewLine collector (SR.ReturnsHeader()) + AppendHardLine collector + collector.Add(tagSpace " ") + WriteElement collector el + + if showRemarks then + match Seq.tryHead (doc.Descendants(XName.op_Implicit "remarks")) with + | None -> () + | Some el -> + AppendHardLine collector + AppendHardLine collector + AppendOnNewLine collector (SR.RemarksHeader()) + AppendHardLine collector + collector.Add(tagSpace " ") + WriteElement collector el + member this.CollectParameter(collector: ITaggedTextCollector, paramName: string) = match tryFindParameter paramName with | None -> () @@ -294,11 +318,12 @@ module internal XmlDocumentation = exnCollector: ITaggedTextCollector, xmlDocReader: XmlDocReader, showExceptions, - showParameters + showParameters, + showRemarks ) = AppendHardLine xmlCollector xmlCollector.StartXMLDoc() - xmlDocReader.CollectSummary(xmlCollector) + xmlDocReader.CollectSummary(xmlCollector, showRemarks) if (showParameters) then xmlDocReader.CollectParameters xmlCollector @@ -315,13 +340,14 @@ module internal XmlDocumentation = processedXml, showExceptions, showParameters, + showRemarks, paramName ) = match XmlDocReader.TryCreate processedXml with | Some xmlDocReader -> match paramName with | Some paramName -> xmlDocReader.CollectParameter(xmlCollector, paramName) - | None -> AppendMemberData(xmlCollector, exnCollector, xmlDocReader, showExceptions, showParameters) + | None -> AppendMemberData(xmlCollector, exnCollector, xmlDocReader, showExceptions, showParameters, showRemarks) | None -> () /// Append Xml documentation contents into the StringBuilder @@ -333,14 +359,15 @@ module internal XmlDocumentation = signature: string, showExceptions: bool, showParameters: bool, + showRemarks, paramName: string option ) = try match GetMemberIndexOfAssembly(fileName) with | Some(index) -> - let _, idx = index.ParseMemberSignature(signature) + let ok, idx = index.ParseMemberSignature(signature) - if idx <> 0u then + if Com.Succeeded(ok) then let ok, xml = index.GetMemberXML(idx) if Com.Succeeded(ok) then @@ -351,6 +378,7 @@ module internal XmlDocumentation = xml, showExceptions, showParameters, + showRemarks, paramName ) | None -> () @@ -367,6 +395,7 @@ module internal XmlDocumentation = xml, showExceptions, showParameters, + showRemarks, paramName ) = match xml with @@ -379,6 +408,7 @@ module internal XmlDocumentation = signature, showExceptions, showParameters, + showRemarks, paramName ) | FSharpXmlDoc.FromXmlText(xmlDoc) -> @@ -391,6 +421,7 @@ module internal XmlDocumentation = processedXml, showExceptions, showParameters, + showRemarks, paramName ) @@ -417,7 +448,13 @@ module internal XmlDocumentation = OverLoadsLimit = 5 } - let BuildSingleTipText (documentationProvider: IDocumentationBuilder, dataTipElement: ToolTipElement, limits: LineLimits) = + let BuildSingleTipText + ( + documentationProvider: IDocumentationBuilder, + dataTipElement: ToolTipElement, + limits: LineLimits, + showRemarks: bool + ) = let { LineLimit = lineLimit @@ -481,7 +518,7 @@ module internal XmlDocumentation = AppendHardLine usageCollector r |> Seq.iter usageCollector.Add) - AppendXmlComment(documentationProvider, xmlCollector, exnCollector, item0.XmlDoc, true, false, item0.ParamName) + AppendXmlComment(documentationProvider, xmlCollector, exnCollector, item0.XmlDoc, true, false, showRemarks, item0.ParamName) ProcessGenericParameters item0.TypeMapping @@ -505,7 +542,8 @@ module internal XmlDocumentation = exnCollector, showText, showExceptions, - showParameters + showParameters, + showRemarks ) = let textCollector: ITaggedTextCollector = TextSanitizingCollector(textCollector, lineLimit = 45) :> _ @@ -590,6 +628,7 @@ module internal XmlDocumentation = item0.XmlDoc, showExceptions, showParameters, + showRemarks, item0.ParamName ) @@ -614,7 +653,8 @@ module internal XmlDocumentation = typeParameterMapCollector, usageCollector, exnCollector, - ToolTipText(dataTipText) + ToolTipText(dataTipText), + showRemarks ) = BuildTipText( documentationProvider, @@ -626,10 +666,11 @@ module internal XmlDocumentation = exnCollector, true, true, - false + false, + showRemarks ) - let BuildMethodOverloadTipText (documentationProvider, textCollector, xmlCollector, ToolTipText(dataTipText), showParams) = + let BuildMethodOverloadTipText (documentationProvider, textCollector, xmlCollector, ToolTipText(dataTipText), showParams, showRemarks) = BuildTipText( documentationProvider, dataTipText, @@ -640,10 +681,11 @@ module internal XmlDocumentation = ignore, false, false, - showParams + showParams, + showRemarks ) - let BuildMethodParamText (documentationProvider, xmlCollector, xml, paramName) = + let BuildMethodParamText (documentationProvider, xmlCollector, xml, paramName, showRemarks) = AppendXmlComment( documentationProvider, TextSanitizingCollector(xmlCollector), @@ -651,6 +693,7 @@ module internal XmlDocumentation = xml, false, true, + showRemarks, Some paramName ) diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index 60e86c9eb96..37bb02d43d2 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -99,6 +99,7 @@ + diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.resx b/vsintegration/src/FSharp.Editor/FSharp.Editor.resx index 4b41551aac0..6678a2d98e3 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.resx +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.resx @@ -180,7 +180,8 @@ Navigation links; Show navigation links as; Solid underline; Dot underline; -Dash underline; +Dash underline; +Show remarks in Quick Info Add an assembly reference to '{0}' @@ -226,6 +227,7 @@ Inline hints; Display inline type hints (preview); Display return type hints (preview); Display inline parameter name hints (preview); +Use Transparent Compiler (experimental); Live Buffers; Use live (unsaved) buffers for analysis @@ -352,7 +354,16 @@ Use live (unsaved) buffers for analysis Convert C# 'using' to F# 'open' + + Add return type annotation + Remove unnecessary parentheses + + Remarks: + + + Returns: + \ No newline at end of file diff --git a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs index 301428f69cb..b492cf1f35f 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs @@ -25,6 +25,7 @@ open Microsoft.CodeAnalysis.ExternalAccess.FSharp open Microsoft.CodeAnalysis.Host.Mef open Microsoft.VisualStudio.FSharp.Editor.Telemetry open CancellableTasks +open FSharp.Compiler.Text #nowarn "9" // NativePtr.toNativeInt #nowarn "57" // Experimental stuff @@ -147,6 +148,8 @@ type internal FSharpWorkspaceServiceFactory [] let enableBackgroundItemKeyStoreAndSemanticClassification = editorOptions.LanguageServicePerformance.EnableBackgroundItemKeyStoreAndSemanticClassification + let useTransparentCompiler = editorOptions.Advanced.UseTransparentCompiler + // Default is false here let solutionCrawler = editorOptions.Advanced.SolutionBackgroundAnalysis @@ -168,6 +171,7 @@ type internal FSharpWorkspaceServiceFactory [] nameof enableBackgroundItemKeyStoreAndSemanticClassification, enableBackgroundItemKeyStoreAndSemanticClassification "captureIdentifiersWhenParsing", enableFastFindReferences + nameof useTransparentCompiler, useTransparentCompiler nameof solutionCrawler, solutionCrawler |], TelemetryThrottlingStrategy.NoThrottling @@ -187,13 +191,19 @@ type internal FSharpWorkspaceServiceFactory [] captureIdentifiersWhenParsing = enableFastFindReferences, documentSource = (if enableLiveBuffers then - DocumentSource.Custom getSource + (DocumentSource.Custom(fun filename -> + async { + match! getSource filename with + | Some source -> return Some(source :> ISourceText) + | None -> return None + })) else DocumentSource.FileSystem), - useSyntaxTreeCache = useSyntaxTreeCache + useSyntaxTreeCache = useSyntaxTreeCache, + useTransparentCompiler = useTransparentCompiler ) - if enableLiveBuffers then + if enableLiveBuffers && not useTransparentCompiler then workspace.WorkspaceChanged.Add(fun args -> if args.DocumentId <> null then cancellableTask { @@ -481,10 +491,10 @@ type internal HackCpsCommandLineChanges else Path.GetFileNameWithoutExtension projectFileName - [] /// This handles commandline change notifications from the Dotnet Project-system /// Prior to VS 15.7 path contained path to project file, post 15.7 contains target binpath /// binpath is more accurate because a project file can have multiple in memory projects based on configuration + [] member _.HandleCommandLineChanges ( path: string, @@ -527,10 +537,10 @@ type internal HackCpsCommandLineChanges let sourcePaths = sources |> Seq.map (fun s -> getFullPath s.Path) |> Seq.toArray - /// Due to an issue in project system, when we close and reopen solution, it sends the CommandLineChanges twice for every project. - /// First time it sends a correct path, sources, references and options. - /// Second time it sends a correct path, empty sources, empty references and empty options, and we rewrite our cache, and fail to colourize the document later. - /// As a workaround, until we have a fix from PS or will move to Roslyn as a source of truth, we will not overwrite the cache in case of empty lists. + // Due to an issue in project system, when we close and reopen solution, it sends the CommandLineChanges twice for every project. + // First time it sends a correct path, sources, references and options. + // Second time it sends a correct path, empty sources, empty references and empty options, and we rewrite our cache, and fail to colourize the document later. + // As a workaround, until we have a fix from PS or will move to Roslyn as a source of truth, we will not overwrite the cache in case of empty lists. if not (sources.IsEmpty && references.IsEmpty && options.IsEmpty) then let workspaceService = diff --git a/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs b/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs index 8a74c5ad795..261c4950ef9 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs @@ -3,6 +3,7 @@ namespace Microsoft.VisualStudio.FSharp.Editor open System.Collections.Concurrent +open System.Collections.Generic open System.Collections.Immutable open System.Threading.Tasks @@ -80,9 +81,19 @@ module internal SymbolHelpers = // TODO: this needs to be a single event with a duration TelemetryReporter.ReportSingleEvent(TelemetryEvents.GetSymbolUsesInProjectsStarted, props) + let snapshotAccumulator = Dictionary() + + let! projects = + projects + |> Seq.map (fun project -> + project.GetFSharpProjectSnapshot(snapshotAccumulator) + |> CancellableTask.map (fun s -> project, s)) + |> CancellableTask.sequential + do! projects - |> Seq.map (fun project -> project.FindFSharpReferencesAsync(symbol, onFound, "getSymbolUsesInProjects")) + |> Seq.map (fun (project, snapshot) -> + project.FindFSharpReferencesAsync(symbol, snapshot, onFound, "getSymbolUsesInProjects")) |> CancellableTask.whenAll TelemetryReporter.ReportSingleEvent(TelemetryEvents.GetSymbolUsesInProjectsFinished, props) diff --git a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs index 891eb960ab3..c0682607360 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs @@ -9,12 +9,326 @@ open Microsoft.VisualStudio.FSharp.Editor open FSharp.Compiler open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.CodeAnalysis.ProjectSnapshot open FSharp.Compiler.Symbols -open Microsoft.VisualStudio.FSharp.Editor.CancellableTasks +open FSharp.Compiler.BuildGraph + +open CancellableTasks + +open Internal.Utilities.Collections +open Newtonsoft.Json +open Newtonsoft.Json.Linq +open System.Text.Json.Nodes + +#nowarn "57" // Experimental stuff + +[] +module internal ProjectCache = + + /// This is a cache to maintain FSharpParsingOptions and FSharpProjectOptions per Roslyn Project. + /// The Roslyn Project is held weakly meaning when it is cleaned up by the GC, the FSharParsingOptions and FSharpProjectOptions will be cleaned up by the GC. + /// At some point, this will be the main caching mechanism for FCS projects instead of FCS itself. + let Projects = + ConditionalWeakTable() + +type Solution with + + /// Get the instance of IFSharpWorkspaceService. + member internal this.GetFSharpWorkspaceService() = + this.Workspace.Services.GetRequiredService() + +module internal FSharpProjectSnapshotSerialization = + + let serializeFileSnapshot (snapshot: FSharpFileSnapshot) = + let output = JObject() + output.Add("FileName", snapshot.FileName) + output.Add("Version", snapshot.Version) + output + + let serializeReferenceOnDisk (reference: ReferenceOnDisk) = + let output = JObject() + output.Add("Path", reference.Path) + output.Add("LastModified", reference.LastModified) + output + + let rec serializeReferencedProject (reference: FSharpReferencedProjectSnapshot) = + let output = JObject() + + match reference with + | FSharpReference(projectOutputFile, snapshot) -> + output.Add("projectOutputFile", projectOutputFile) + output.Add("snapshot", serializeSnapshot snapshot) + + output + + and serializeSnapshot (snapshot: FSharpProjectSnapshot) = + + let output = JObject() + let snapshot = snapshot.ProjectSnapshot + + output.Add("ProjectFileName", snapshot.ProjectFileName) + output.Add("ProjectId", (snapshot.ProjectId |> Option.defaultValue null |> JToken.FromObject)) + output.Add("SourceFiles", snapshot.SourceFiles |> Seq.map serializeFileSnapshot |> JArray) + output.Add("ReferencesOnDisk", snapshot.ReferencesOnDisk |> Seq.map serializeReferenceOnDisk |> JArray) + output.Add("OtherOptions", JArray(snapshot.OtherOptions)) + output.Add("ReferencedProjects", snapshot.ReferencedProjects |> Seq.map serializeReferencedProject |> JArray) + output.Add("IsIncompleteTypeCheckEnvironment", snapshot.IsIncompleteTypeCheckEnvironment) + output.Add("UseScriptResolutionRules", snapshot.UseScriptResolutionRules) + output.Add("LoadTime", snapshot.LoadTime) + // output.Add("UnresolvedReferences", snapshot.UnresolvedReferences) + output.Add( + "OriginalLoadReferences", + snapshot.OriginalLoadReferences + |> Seq.map (fun (r: Text.range, a, b) -> JArray(r.FileName, r.Start, r.End, a, b)) + |> JArray + ) + + output.Add("Stamp", (snapshot.Stamp |> (Option.defaultValue 0) |> JToken.FromObject)) + + output + + let dumpToJson (snapshot) = + + let jObject = serializeSnapshot snapshot + + let json = jObject.ToString(Formatting.Indented) + + json + +open FSharpProjectSnapshotSerialization +open System.Collections.Concurrent [] module private CheckerExtensions = + let snapshotCache = AsyncMemoize(1000, 500, "SnapshotCache") + + let latestSnapshots = ConcurrentDictionary<_, _>() + + let exist xs = xs |> Seq.isEmpty |> not + + let getFSharpOptionsForProject (this: Project) = + if not this.IsFSharp then + raise (OperationCanceledException("Project is not a FSharp project.")) + else + match ProjectCache.Projects.TryGetValue(this) with + | true, result -> CancellableTask.singleton result + | _ -> + cancellableTask { + + let! ct = CancellableTask.getCancellationToken () + + let service = this.Solution.GetFSharpWorkspaceService() + let projectOptionsManager = service.FSharpProjectOptionsManager + + match! projectOptionsManager.TryGetOptionsByProject(this, ct) with + | ValueNone -> return raise (OperationCanceledException("FSharp project options not found.")) + | ValueSome(parsingOptions, projectOptions) -> + let result = + (service.Checker, projectOptionsManager, parsingOptions, projectOptions) + + return ProjectCache.Projects.GetValue(this, ConditionalWeakTable<_, _>.CreateValueCallback(fun _ -> result)) + } + + let documentToSnapshot (document: Document) = + cancellableTask { + let! version = document.GetTextVersionAsync() + + let getSource () = + task { + let! sourceText = document.GetTextAsync() + return sourceText.ToFSharpSourceText() + } + + return FSharpFileSnapshot(FileName = document.FilePath, Version = version.ToString(), GetSource = getSource) + } + + let getReferencedProjectVersions (project: Project) = + project.GetAllProjectsThisProjectDependsOn() + |> Seq.map (fun r ct -> r.GetDependentSemanticVersionAsync(ct)) + |> CancellableTask.whenAll + |> CancellableTask.map (Seq.map (fun x -> x.ToString()) >> Set) + + let getOnDiskReferences (options: FSharpProjectOptions) = + options.OtherOptions + |> Seq.filter (fun x -> x.StartsWith("-r:")) + |> Seq.map (fun x -> + let path = x.Substring(3) + + { + Path = path + LastModified = System.IO.File.GetLastWriteTimeUtc path + }) + |> Seq.toList + + let createProjectSnapshot (snapshotAccumulatorOpt) (project: Project) (options: FSharpProjectOptions option) = + cancellableTask { + + let! options = + match options with + | Some options -> CancellableTask.singleton options + | None -> + cancellableTask { + let! _, _, _, options = getFSharpOptionsForProject project + return options + } + + let! projectVersion = project.GetDependentSemanticVersionAsync() + + let! referenceVersions = getReferencedProjectVersions project + + let updatedSnapshot = + match project.IsTransparentCompilerSnapshotReuseEnabled, latestSnapshots.TryGetValue project.Id with + | true, (true, (_, _, oldReferenceVersions, _, _)) when referenceVersions <> oldReferenceVersions -> + System.Diagnostics.Trace.TraceWarning "Reference versions changed" + None + + | true, (true, (_, _, _, _, oldSnapshot: FSharpProjectSnapshot)) when + oldSnapshot.ProjectSnapshot.ReferencesOnDisk <> (getOnDiskReferences options) + -> + System.Diagnostics.Trace.TraceWarning "References on disk changed" + None + + | true, (true, (_, oldProjectVersion, _, _, oldSnapshot: FSharpProjectSnapshot)) when projectVersion = oldProjectVersion -> + Some(CancellableTask.singleton oldSnapshot) + + | true, (true, (oldProject, _oldProjectVersion, _oldReferencesVersion, oldOptions, oldSnapshot: FSharpProjectSnapshot)) when + FSharpProjectOptions.AreSameForChecking(options, oldOptions) + -> + + let changes = project.GetChanges(oldProject) + + if + changes.GetAddedDocuments() |> exist + || changes.GetRemovedDocuments() |> exist + || changes.GetAddedMetadataReferences() |> exist + || changes.GetRemovedMetadataReferences() |> exist + || changes.GetAddedProjectReferences() |> exist + || changes.GetRemovedProjectReferences() |> exist + then + // if any of that happened, we create it from scratch + System.Diagnostics.Trace.TraceWarning "Project change not covered by options - suspicious" + None + + else + // we build it from the previous one + + let changedDocuments = changes.GetChangedDocuments() |> Seq.toList + + System.Diagnostics.Trace.TraceInformation + $"Incremental update of FSharpProjectSnapshot ({oldSnapshot.Label}) - {changedDocuments.Length} changed documents" + + if changedDocuments.Length = 0 then + // this is suspicious + let _breakpoint = "here" + () + + changedDocuments + |> Seq.map (project.GetDocument >> documentToSnapshot) + |> CancellableTask.whenAll + |> CancellableTask.map (Array.toList >> oldSnapshot.Replace) + |> Some + + | _ -> None + + let! newSnapshot = + + match updatedSnapshot with + | Some snapshot -> snapshot + | _ -> + cancellableTask { + + let solution = project.Solution + + let projects = + solution.Projects + |> Seq.map (fun p -> p.FilePath, p.Documents |> Seq.map (fun d -> d.FilePath, d) |> Map) + |> Map + + let getFileSnapshot (options: FSharpProjectOptions) path = + async { + let project = projects.TryFind options.ProjectFileName + + if project.IsNone then + System.Diagnostics.Trace.TraceError( + "Could not find project {0} in solution {1}", + options.ProjectFileName, + solution.FilePath + ) + + let documentOpt = project |> Option.bind (Map.tryFind path) + + let! version, getSource = + match documentOpt with + | Some document -> + async { + + let! version = document.GetTextVersionAsync() |> Async.AwaitTask + + let getSource () = + task { + let! sourceText = document.GetTextAsync() + return sourceText.ToFSharpSourceText() + } + + return version.ToString(), getSource + + } + | None -> + // This happens with files that are read from /obj + + // Fall back to file system + let version = System.IO.File.GetLastWriteTimeUtc(path) + + let getSource () = + task { return System.IO.File.ReadAllText(path) |> FSharp.Compiler.Text.SourceTextNew.ofString } + + async.Return(version.ToString(), getSource) + + return FSharpFileSnapshot(FileName = path, Version = version, GetSource = getSource) + } + + let! snapshot = + FSharpProjectSnapshot.FromOptions(options, getFileSnapshot, ?snapshotAccumulator = snapshotAccumulatorOpt) + + System.Diagnostics.Trace.TraceInformation $"Created new FSharpProjectSnapshot ({snapshot.Label})" + + return snapshot + } + + let latestSnapshotData = + project, projectVersion, referenceVersions, options, newSnapshot + + latestSnapshots.AddOrUpdate(project.Id, latestSnapshotData, (fun _ _ -> latestSnapshotData)) + |> ignore + + return newSnapshot + } + + let getOrCreateSnapshotForProject (project: Project) options snapshotAccumulatorOpt = + + let key = + { new ICacheKey<_, _> with + member _.GetKey() = project.Id + member _.GetVersion() = project + member _.GetLabel() = project.FilePath + } + + snapshotCache.Get( + key, + node { + let! ct = NodeCode.CancellationToken + + return! + createProjectSnapshot snapshotAccumulatorOpt project options ct + |> NodeCode.AwaitTask + } + ) + |> Async.AwaitNodeCode + + let getProjectSnapshotForDocument (document: Document, options: FSharpProjectOptions) = + getOrCreateSnapshotForProject document.Project (Some options) None + type FSharpChecker with /// Parse the source text from the Roslyn document. @@ -26,6 +340,32 @@ module private CheckerExtensions = return! checker.ParseFile(document.FilePath, sourceText.ToFSharpSourceText(), parsingOptions, userOpName = userOpName) } + member checker.ParseDocumentUsingTransparentCompiler(document: Document, options: FSharpProjectOptions, userOpName: string) = + cancellableTask { + let! projectSnapshot = getProjectSnapshotForDocument (document, options) + return! checker.ParseFile(document.FilePath, projectSnapshot, userOpName = userOpName) + } + + member checker.ParseAndCheckDocumentUsingTransparentCompiler + ( + document: Document, + options: FSharpProjectOptions, + userOpName: string + ) = + cancellableTask { + + checker.TransparentCompiler.SetCacheSizeFactor(document.Project.TransparentCompilerCacheFactor) + + let! projectSnapshot = getProjectSnapshotForDocument (document, options) + + let! (parseResults, checkFileAnswer) = checker.ParseAndCheckFileInProject(document.FilePath, projectSnapshot, userOpName) + + return + match checkFileAnswer with + | FSharpCheckFileAnswer.Aborted -> None + | FSharpCheckFileAnswer.Succeeded(checkFileResults) -> Some(parseResults, checkFileResults) + } + /// Parse and check the source text from the Roslyn document with possible stale results. member checker.ParseAndCheckDocumentWithPossibleStaleResults ( @@ -106,28 +446,18 @@ module private CheckerExtensions = ?allowStaleResults: bool ) = cancellableTask { - let allowStaleResults = - match allowStaleResults with - | Some b -> b - | _ -> document.Project.IsFSharpStaleCompletionResultsEnabled - - return! checker.ParseAndCheckDocumentWithPossibleStaleResults(document, options, allowStaleResults, userOpName = userOpName) - } -[] -module internal ProjectCache = - - /// This is a cache to maintain FSharpParsingOptions and FSharpProjectOptions per Roslyn Project. - /// The Roslyn Project is held weakly meaning when it is cleaned up by the GC, the FSharParsingOptions and FSharpProjectOptions will be cleaned up by the GC. - /// At some point, this will be the main caching mechanism for FCS projects instead of FCS itself. - let Projects = - ConditionalWeakTable() - -type Solution with + if document.Project.UseTransparentCompiler then + return! checker.ParseAndCheckDocumentUsingTransparentCompiler(document, options, userOpName) + else + let allowStaleResults = + match allowStaleResults with + | Some b -> b + | _ -> document.Project.IsFSharpStaleCompletionResultsEnabled - /// Get the instance of IFSharpWorkspaceService. - member internal this.GetFSharpWorkspaceService() = - this.Workspace.Services.GetRequiredService() + return! + checker.ParseAndCheckDocumentWithPossibleStaleResults(document, options, allowStaleResults, userOpName = userOpName) + } type Document with @@ -195,8 +525,12 @@ type Document with /// Parses the given F# document. member this.GetFSharpParseResultsAsync(userOpName) = cancellableTask { - let! checker, _, parsingOptions, _ = this.GetFSharpCompilationOptionsAsync(userOpName) - return! checker.ParseDocument(this, parsingOptions, userOpName) + let! checker, _, parsingOptions, options = this.GetFSharpCompilationOptionsAsync(userOpName) + + if this.Project.UseTransparentCompiler then + return! checker.ParseDocumentUsingTransparentCompiler(this, options, userOpName) + else + return! checker.ParseDocument(this, parsingOptions, userOpName) } /// Parses and checks the given F# document. @@ -213,7 +547,15 @@ type Document with member this.GetFSharpSemanticClassificationAsync(userOpName) = cancellableTask { let! checker, _, _, projectOptions = this.GetFSharpCompilationOptionsAsync(userOpName) - let! result = checker.GetBackgroundSemanticClassificationForFile(this.FilePath, projectOptions) + + let! result = + if this.Project.UseTransparentCompiler then + async { + let! projectSnapshot = getProjectSnapshotForDocument (this, projectOptions) + return! checker.GetBackgroundSemanticClassificationForFile(this.FilePath, projectSnapshot) + } + else + checker.GetBackgroundSemanticClassificationForFile(this.FilePath, projectOptions) return result @@ -221,18 +563,22 @@ type Document with } /// Find F# references in the given F# document. - member inline this.FindFSharpReferencesAsync(symbol, [] onFound, userOpName) = + member inline this.FindFSharpReferencesAsync(symbol, projectSnapshot: FSharpProjectSnapshot, [] onFound, userOpName) = cancellableTask { let! checker, _, _, projectOptions = this.GetFSharpCompilationOptionsAsync(userOpName) let! symbolUses = - checker.FindBackgroundReferencesInFile( - this.FilePath, - projectOptions, - symbol, - canInvalidateProject = false, - fastCheck = this.Project.IsFastFindReferencesEnabled - ) + + if this.Project.UseTransparentCompiler then + checker.FindBackgroundReferencesInFile(this.FilePath, projectSnapshot, symbol) + else + checker.FindBackgroundReferencesInFile( + this.FilePath, + projectOptions, + symbol, + canInvalidateProject = false, + fastCheck = this.Project.IsFastFindReferencesEnabled + ) do! symbolUses @@ -267,7 +613,7 @@ type Document with type Project with /// Find F# references in the given project. - member this.FindFSharpReferencesAsync(symbol: FSharpSymbol, onFound, userOpName) = + member this.FindFSharpReferencesAsync(symbol: FSharpSymbol, projectSnapshot, onFound, userOpName) = cancellableTask { let declarationLocation = @@ -307,32 +653,15 @@ type Project with if this.IsFastFindReferencesEnabled then do! documents - |> Seq.map (fun doc -> doc.FindFSharpReferencesAsync(symbol, (fun range -> onFound doc range), userOpName)) + |> Seq.map (fun doc -> + doc.FindFSharpReferencesAsync(symbol, projectSnapshot, (fun range -> onFound doc range), userOpName)) |> CancellableTask.whenAll else for doc in documents do - do! doc.FindFSharpReferencesAsync(symbol, (fun range -> onFound doc range), userOpName) + do! doc.FindFSharpReferencesAsync(symbol, projectSnapshot, (onFound doc), userOpName) } - member this.GetFSharpCompilationOptionsAsync() = - if not this.IsFSharp then - raise (OperationCanceledException("Project is not a FSharp project.")) - else - match ProjectCache.Projects.TryGetValue(this) with - | true, result -> CancellableTask.singleton result - | _ -> - cancellableTask { - - let! ct = CancellableTask.getCancellationToken () - - let service = this.Solution.GetFSharpWorkspaceService() - let projectOptionsManager = service.FSharpProjectOptionsManager + member this.GetFSharpCompilationOptionsAsync() = this |> getFSharpOptionsForProject - match! projectOptionsManager.TryGetOptionsByProject(this, ct) with - | ValueNone -> return raise (OperationCanceledException("FSharp project options not found.")) - | ValueSome(parsingOptions, projectOptions) -> - let result = - (service.Checker, projectOptionsManager, parsingOptions, projectOptions) - - return ProjectCache.Projects.GetValue(this, ConditionalWeakTable<_, _>.CreateValueCallback(fun _ -> result)) - } + member this.GetFSharpProjectSnapshot(?snapshotAccumulator) = + cancellableTask { return! getOrCreateSnapshotForProject this None snapshotAccumulator } diff --git a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs index c531d386af3..e9b7f60252a 100644 --- a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs +++ b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs @@ -46,6 +46,7 @@ type QuickInfoOptions = DisplayLinks: bool UnderlineStyle: QuickInfoUnderlineStyle DescriptionWidth: int option + ShowRemarks: bool } static member Default = @@ -53,6 +54,7 @@ type QuickInfoOptions = DisplayLinks = true UnderlineStyle = QuickInfoUnderlineStyle.Solid DescriptionWidth = None + ShowRemarks = true } [] @@ -81,6 +83,7 @@ type CodeFixesOptions = type LanguageServicePerformanceOptions = { EnableInMemoryCrossProjectReferences: bool + TransparentCompilerCacheFactor: int AllowStaleCompletionResults: bool TimeUntilStaleCompletion: int EnableParallelReferenceResolution: bool @@ -95,6 +98,7 @@ type LanguageServicePerformanceOptions = static member Default = { EnableInMemoryCrossProjectReferences = true + TransparentCompilerCacheFactor = 100 AllowStaleCompletionResults = true TimeUntilStaleCompletion = 2000 // In ms, so this is 2 seconds EnableParallelReferenceResolution = false @@ -115,6 +119,8 @@ type AdvancedOptions = IsInlineParameterNameHintsEnabled: bool IsInlineReturnTypeHintsEnabled: bool IsUseLiveBuffersEnabled: bool + UseTransparentCompiler: bool + TransparentCompilerSnapshotReuse: bool SendAdditionalTelemetry: bool SolutionBackgroundAnalysis: bool } @@ -126,6 +132,8 @@ type AdvancedOptions = IsInlineTypeHintsEnabled = false IsInlineParameterNameHintsEnabled = false IsInlineReturnTypeHintsEnabled = false + UseTransparentCompiler = false + TransparentCompilerSnapshotReuse = false IsUseLiveBuffersEnabled = true SendAdditionalTelemetry = true SolutionBackgroundAnalysis = false @@ -199,6 +207,7 @@ module internal OptionsUI = bindRadioButton view.dash path QuickInfoUnderlineStyle.Dash bindCheckBox view.displayLinks (nameof QuickInfoOptions.Default.DisplayLinks) bindDescriptionWidthTextBox view.descriptionWidth (nameof QuickInfoOptions.Default.DescriptionWidth) + bindCheckBox view.showRemarks (nameof QuickInfoOptions.Default.ShowRemarks) upcast view [] @@ -262,3 +271,11 @@ module EditorOptionsExtensions = member this.IsFastFindReferencesEnabled = this.EditorOptions.LanguageServicePerformance.EnableFastFindReferencesAndRename + + member this.UseTransparentCompiler = this.EditorOptions.Advanced.UseTransparentCompiler + + member this.IsTransparentCompilerSnapshotReuseEnabled = + this.EditorOptions.Advanced.TransparentCompilerSnapshotReuse + + member this.TransparentCompilerCacheFactor = + this.EditorOptions.LanguageServicePerformance.TransparentCompilerCacheFactor diff --git a/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs b/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs index ae79300ee85..581a6a7fef3 100644 --- a/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs +++ b/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs @@ -31,7 +31,12 @@ type internal FSharpAsyncQuickInfoSource let getSingleContent (data: ToolTipElement) = let symbol, description, documentation = - XmlDocumentation.BuildSingleTipText(documentationBuilder, data, XmlDocumentation.DefaultLineLimits) + XmlDocumentation.BuildSingleTipText( + documentationBuilder, + data, + XmlDocumentation.DefaultLineLimits, + editorOptions.QuickInfo.ShowRemarks + ) let getLinkTooltip filePath = let solutionDir = Path.GetDirectoryName(document.Project.Solution.FilePath) diff --git a/vsintegration/src/FSharp.Editor/Refactor/AddReturnType.fs b/vsintegration/src/FSharp.Editor/Refactor/AddReturnType.fs new file mode 100644 index 00000000000..b3c586b445e --- /dev/null +++ b/vsintegration/src/FSharp.Editor/Refactor/AddReturnType.fs @@ -0,0 +1,118 @@ +namespace Microsoft.VisualStudio.FSharp.Editor + +open System.Composition +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.Symbols +open FSharp.Compiler.Text + +open Microsoft.CodeAnalysis.Text +open Microsoft.CodeAnalysis.CodeRefactorings +open Microsoft.CodeAnalysis.CodeActions +open CancellableTasks + +[] +type internal AddReturnType [] () = + inherit CodeRefactoringProvider() + + static member isValidMethodWithoutTypeAnnotation + (symbolUse: FSharpSymbolUse) + (parseFileResults: FSharpParseFileResults) + (funcOrValue: FSharpMemberOrFunctionOrValue) + = + let typeAnnotationRange = + parseFileResults.TryRangeOfReturnTypeHint(symbolUse.Range.Start, false) + + let res = + funcOrValue.CompiledName = funcOrValue.DisplayName + && funcOrValue.IsFunction + && not (parseFileResults.IsBindingALambdaAtPosition symbolUse.Range.Start) + && not (funcOrValue.ReturnParameter.Type.IsUnresolved) + && not (parseFileResults.IsTypeAnnotationGivenAtPosition symbolUse.Range.Start) + && not typeAnnotationRange.IsNone + + match (res, typeAnnotationRange) with + | (true, Some tr) -> Some(funcOrValue, tr) + | (_, _) -> None + + static member refactor + (context: CodeRefactoringContext) + (memberFunc: FSharpMemberOrFunctionOrValue, typeRange: Range, symbolUse: FSharpSymbolUse) + = + let title = SR.AddReturnTypeAnnotation() + + let getChangedText (sourceText: SourceText) = + let returnType = memberFunc.ReturnParameter.Type + + let inferredType = + let res = returnType.Format symbolUse.DisplayContext + + if returnType.HasTypeDefinition then + res + else + $"({res})".Replace(" ", "") + + let textSpan = RoslynHelpers.FSharpRangeToTextSpan(sourceText, typeRange) + let textChange = TextChange(textSpan, $": {inferredType} ") + sourceText.WithChanges(textChange) + + let codeActionFunc = + cancellableTask { + let! cancellationToken = CancellableTask.getCancellationToken () + let! sourceText = context.Document.GetTextAsync(cancellationToken) + let changedText = getChangedText sourceText + + let newDocument = context.Document.WithText(changedText) + return newDocument + } + + let codeAction = CodeAction.Create(title, codeActionFunc, title) + + do context.RegisterRefactoring(codeAction) + + static member ofFSharpMemberOrFunctionOrValue(symbol: FSharpSymbol) = + match symbol with + | :? FSharpMemberOrFunctionOrValue as v -> Some v + | _ -> None + + override _.ComputeRefactoringsAsync context = + cancellableTask { + let document = context.Document + let position = context.Span.Start + let! sourceText = document.GetTextAsync() + let textLine = sourceText.Lines.GetLineFromPosition position + let textLinePos = sourceText.Lines.GetLinePosition position + let fcsTextLineNumber = Line.fromZ textLinePos.Line + + let! lexerSymbol = + document.TryFindFSharpLexerSymbolAsync(position, SymbolLookupKind.Greedy, false, false, nameof (AddReturnType)) + + let! (parseFileResults, checkFileResults) = document.GetFSharpParseAndCheckResultsAsync(nameof (AddReturnType)) + + let symbolUseOpt = + lexerSymbol + |> Option.bind (fun lexer -> + checkFileResults.GetSymbolUseAtLocation( + fcsTextLineNumber, + lexer.Ident.idRange.EndColumn, + textLine.ToString(), + lexer.FullIsland + )) + + let memberFuncOpt = + symbolUseOpt + |> Option.bind (fun sym -> sym.Symbol |> AddReturnType.ofFSharpMemberOrFunctionOrValue) + + match (symbolUseOpt, memberFuncOpt) with + | (Some symbolUse, Some memberFunc) -> + let isValidMethod = + memberFunc + |> AddReturnType.isValidMethodWithoutTypeAnnotation symbolUse parseFileResults + + match isValidMethod with + | Some(memberFunc, typeRange) -> do AddReturnType.refactor context (memberFunc, typeRange, symbolUse) + | None -> () + | _ -> () + + return () + } + |> CancellableTask.startAsTask context.CancellationToken diff --git a/vsintegration/src/FSharp.Editor/Telemetry/TelemetryReporter.fs b/vsintegration/src/FSharp.Editor/Telemetry/TelemetryReporter.fs index 2a520d72066..b841b7e8cd6 100644 --- a/vsintegration/src/FSharp.Editor/Telemetry/TelemetryReporter.fs +++ b/vsintegration/src/FSharp.Editor/Telemetry/TelemetryReporter.fs @@ -105,9 +105,11 @@ type TelemetryReporter private (name: string, props: (string * obj) array, stopw TelemetryService.DefaultSession.IsUserMicrosoftInternal else let workspace = componentModel.GetService() + let options = workspace.Services.GetService() TelemetryService.DefaultSession.IsUserMicrosoftInternal - || workspace.Services.GetService().Advanced.SendAdditionalTelemetry) + || options.Advanced.SendAdditionalTelemetry + || options.Advanced.UseTransparentCompiler) static member ReportFault(name, ?severity: FaultSeverity, ?e: exn) = if TelemetryReporter.SendAdditionalTelemetry.Value then diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.cs.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.cs.xlf index 5db40f51628..182fc895c61 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.cs.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.cs.xlf @@ -22,6 +22,11 @@ Přidejte klíčové slovo new. + + Add return type annotation + Add return type annotation + + Add type annotation Přidat anotaci typu @@ -36,6 +41,7 @@ Inline hints; Display inline type hints (preview); Display return type hints (preview); Display inline parameter name hints (preview); +Use Transparent Compiler (experimental); Live Buffers; Use live (unsaved) buffers for analysis Vodítka struktury bloků; @@ -195,8 +201,9 @@ Navigation links; Show navigation links as; Solid underline; Dot underline; -Dash underline; - Formátování; +Dash underline; +Show remarks in Quick Info + Formátování; Upřednostňovaná šířka popisu ve znacích; Formátování podpisu na danou šířku přidáním konců řádků podle pravidel syntaxe F#; Navigační odkazy; @@ -206,6 +213,11 @@ Tečkované podtržení; Přerušované podtržení; + + Remarks: + Remarks: + + Remove 'return' Odebrat return @@ -241,6 +253,11 @@ Přerušované podtržení; Přejmenujte {0} na _. + + Returns: + Returns: + + Simplify name Zjednodušte název. diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.de.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.de.xlf index 31ffc4c8342..5a8c128c134 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.de.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.de.xlf @@ -22,6 +22,11 @@ Schlüsselwort "new" hinzufügen + + Add return type annotation + Add return type annotation + + Add type annotation Typanmerkung hinzufügen @@ -36,6 +41,7 @@ Inline hints; Display inline type hints (preview); Display return type hints (preview); Display inline parameter name hints (preview); +Use Transparent Compiler (experimental); Live Buffers; Use live (unsaved) buffers for analysis Führungslinien für Blockstruktur; @@ -195,8 +201,9 @@ Navigation links; Show navigation links as; Solid underline; Dot underline; -Dash underline; - Formatierung; +Dash underline; +Show remarks in Quick Info + Formatierung; Bevorzugte Beschreibungsbreite in Zeichen; Signatur in der angegebenen Breite formatieren, indem Zeilenumbrüche hinzugefügt werden, die den F#-Syntaxregeln entsprechen; Navigationslinks; @@ -206,6 +213,11 @@ Punkt unterstrichen; Strich unterstrichen; + + Remarks: + Remarks: + + Remove 'return' "return" entfernen @@ -241,6 +253,11 @@ Strich unterstrichen; "{0}" in "_" umbenennen + + Returns: + Returns: + + Simplify name Namen vereinfachen diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.es.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.es.xlf index dceb8706e99..e313f8ceefc 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.es.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.es.xlf @@ -22,6 +22,11 @@ Agregar "nueva" palabra clave + + Add return type annotation + Add return type annotation + + Add type annotation Agregar una anotación de tipo @@ -36,6 +41,7 @@ Inline hints; Display inline type hints (preview); Display return type hints (preview); Display inline parameter name hints (preview); +Use Transparent Compiler (experimental); Live Buffers; Use live (unsaved) buffers for analysis Guías de estructura de bloques; @@ -197,8 +203,9 @@ Navigation links; Show navigation links as; Solid underline; Dot underline; -Dash underline; - Formato; +Dash underline; +Show remarks in Quick Info + Formato; Ancho de descripción preferido en caracteres; Dar formato a la firma con el ancho dado agregando saltos de línea que cumplan las reglas de sintaxis de F#; Vínculos de navegación; @@ -208,6 +215,11 @@ Subrayado de punto; Subrayado de guion; + + Remarks: + Remarks: + + Remove 'return' Quitar "return" @@ -243,6 +255,11 @@ Subrayado de guion; Cambiar nombre de "{0}" por "_" + + Returns: + Returns: + + Simplify name Simplificar nombre diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.fr.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.fr.xlf index db53640c9a5..36245222af1 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.fr.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.fr.xlf @@ -22,6 +22,11 @@ Ajouter le mot clé 'new' + + Add return type annotation + Add return type annotation + + Add type annotation Ajouter une annotation de type @@ -36,6 +41,7 @@ Inline hints; Display inline type hints (preview); Display return type hints (preview); Display inline parameter name hints (preview); +Use Transparent Compiler (experimental); Live Buffers; Use live (unsaved) buffers for analysis Guides de structure de bloc ; @@ -195,8 +201,9 @@ Navigation links; Show navigation links as; Solid underline; Dot underline; -Dash underline; - Formatage; +Dash underline; +Show remarks in Quick Info + Formatage; Largeur de description préférée en caractères ; Mettre en forme la signature à la largeur donnée en ajoutant des sauts de ligne conformes aux règles de syntaxe F# ; Liens de navigation ; @@ -206,6 +213,11 @@ Soulignement pointé ; Soulignement en tirets ; + + Remarks: + Remarks: + + Remove 'return' Supprimer 'return' @@ -241,6 +253,11 @@ Soulignement en tirets ; Renommer '{0}' en '_' + + Returns: + Returns: + + Simplify name Simplifier le nom diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.it.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.it.xlf index 97feb5816e2..12f274dffbd 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.it.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.it.xlf @@ -22,6 +22,11 @@ Aggiungi la parola chiave 'new' + + Add return type annotation + Add return type annotation + + Add type annotation Aggiungere l'annotazione di tipo @@ -36,6 +41,7 @@ Inline hints; Display inline type hints (preview); Display return type hints (preview); Display inline parameter name hints (preview); +Use Transparent Compiler (experimental); Live Buffers; Use live (unsaved) buffers for analysis Guide per strutture a blocchi; @@ -195,8 +201,9 @@ Navigation links; Show navigation links as; Solid underline; Dot underline; -Dash underline; - Formattazione; +Dash underline; +Show remarks in Quick Info + Formattazione; Larghezza descrizione preferita in caratteri; Formatta la firma in base alla larghezza specificata aggiungendo interruzioni di riga conformi alle regole di sintassi F#; Collegamenti di spostamento; @@ -206,6 +213,11 @@ Sottolineatura a punto; Sottolineatura a trattini; + + Remarks: + Remarks: + + Remove 'return' Rimuovi 'return' @@ -241,6 +253,11 @@ Sottolineatura a trattini; Rinomina '{0}' in '_' + + Returns: + Returns: + + Simplify name Semplifica nome diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ja.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ja.xlf index f9682a8d5fd..1a23fcf5d9e 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ja.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ja.xlf @@ -22,6 +22,11 @@ 'new' キーワードを追加する + + Add return type annotation + Add return type annotation + + Add type annotation 型の注釈の追加 @@ -36,6 +41,7 @@ Inline hints; Display inline type hints (preview); Display return type hints (preview); Display inline parameter name hints (preview); +Use Transparent Compiler (experimental); Live Buffers; Use live (unsaved) buffers for analysis ブロック構造ガイド; @@ -195,8 +201,9 @@ Navigation links; Show navigation links as; Solid underline; Dot underline; -Dash underline; - 書式 設定; +Dash underline; +Show remarks in Quick Info + 書式 設定; 希望の説明の幅 (文字数); F# 構文規則に準拠するよう、改行を追加して指定された幅に署名を書式設定します; ナビゲーション リンク; @@ -206,6 +213,11 @@ F# 構文規則に準拠するよう、改行を追加して指定された幅 ダッシュ下線; + + Remarks: + Remarks: + + Remove 'return' 'return' の削除 @@ -241,6 +253,11 @@ F# 構文規則に準拠するよう、改行を追加して指定された幅 '{0}' から '_' に名前を変更する + + Returns: + Returns: + + Simplify name 名前を単純化する diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ko.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ko.xlf index 638099fe0fb..1f58583afd2 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ko.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ko.xlf @@ -22,6 +22,11 @@ 'new' 키워드 추가 + + Add return type annotation + Add return type annotation + + Add type annotation 형식 주석 추가 @@ -36,6 +41,7 @@ Inline hints; Display inline type hints (preview); Display return type hints (preview); Display inline parameter name hints (preview); +Use Transparent Compiler (experimental); Live Buffers; Use live (unsaved) buffers for analysis 블록 구조 안내선; @@ -196,8 +202,9 @@ Navigation links; Show navigation links as; Solid underline; Dot underline; -Dash underline; - 서식; +Dash underline; +Show remarks in Quick Info + 서식; 기본 설정 문자 설명 너비; F# 구문 규칙에 맞는 줄바꿈을 추가하여 지정된 너비에 서명 서식 지정; 탐색 링크; @@ -207,6 +214,11 @@ F# 구문 규칙에 맞는 줄바꿈을 추가하여 지정된 너비에 서명 대시 밑줄; + + Remarks: + Remarks: + + Remove 'return' 'return' 제거 @@ -242,6 +254,11 @@ F# 구문 규칙에 맞는 줄바꿈을 추가하여 지정된 너비에 서명 '{0}'의 이름을 '_'로 바꾸기 + + Returns: + Returns: + + Simplify name 이름 단순화 diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pl.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pl.xlf index cc17e6d540e..24392a0e18e 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pl.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pl.xlf @@ -22,6 +22,11 @@ Dodaj słowo kluczowe „new” + + Add return type annotation + Add return type annotation + + Add type annotation Dodaj adnotację typu @@ -36,6 +41,7 @@ Inline hints; Display inline type hints (preview); Display return type hints (preview); Display inline parameter name hints (preview); +Use Transparent Compiler (experimental); Live Buffers; Use live (unsaved) buffers for analysis Przewodniki po strukturze bloku; @@ -195,8 +201,9 @@ Navigation links; Show navigation links as; Solid underline; Dot underline; -Dash underline; - Formatowanie; +Dash underline; +Show remarks in Quick Info + Formatowanie; Preferowana szerokość opisu w znakach; Sformatuj sygnaturę na daną szerokość, dodając podziały wierszy zgodne z regułami składni języka F#; Linki nawigacji; @@ -206,6 +213,11 @@ Podkreślenie kropką; Podkreślenie kreską; + + Remarks: + Remarks: + + Remove 'return' Usuń element „return” @@ -241,6 +253,11 @@ Podkreślenie kreską; Zmień nazwę z „{0}” na „_” + + Returns: + Returns: + + Simplify name Uprość nazwę diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf index 492073cacb0..85a79352133 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf @@ -22,6 +22,11 @@ Adicionar a palavra-chave 'new' + + Add return type annotation + Add return type annotation + + Add type annotation Adicionar uma anotação de tipo @@ -36,6 +41,7 @@ Inline hints; Display inline type hints (preview); Display return type hints (preview); Display inline parameter name hints (preview); +Use Transparent Compiler (experimental); Live Buffers; Use live (unsaved) buffers for analysis Guias de Estrutura de Bloco; @@ -195,8 +201,9 @@ Navigation links; Show navigation links as; Solid underline; Dot underline; -Dash underline; - Formatação; +Dash underline; +Show remarks in Quick Info + Formatação; Largura da descrição preferida em caracteres; Formate a assinatura para a largura especificada adicionando quebras de linha em conformidade com as regras de sintaxe do F#; Links de navegação; @@ -206,6 +213,11 @@ Ponto sublinhado; Traço sublinhado; + + Remarks: + Remarks: + + Remove 'return' Remover 'return' @@ -241,6 +253,11 @@ Traço sublinhado; Renomear '{0}' para '_' + + Returns: + Returns: + + Simplify name Simplificar o nome diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ru.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ru.xlf index b8549511a9f..357494b37b2 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ru.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ru.xlf @@ -22,6 +22,11 @@ Добавить ключевое слово "new" + + Add return type annotation + Add return type annotation + + Add type annotation Добавить заметку типа @@ -36,6 +41,7 @@ Inline hints; Display inline type hints (preview); Display return type hints (preview); Display inline parameter name hints (preview); +Use Transparent Compiler (experimental); Live Buffers; Use live (unsaved) buffers for analysis Руководства по блочной структуре; @@ -195,8 +201,9 @@ Navigation links; Show navigation links as; Solid underline; Dot underline; -Dash underline; - Форматирование; +Dash underline; +Show remarks in Quick Info + Форматирование; Предпочитаемая ширина описания в символах; Форматирование подписи до заданной ширины путем добавления разрывов строк в соответствии с правилами синтаксиса F#; Ссылки навигации; @@ -206,6 +213,11 @@ Dash underline; Штриховое подчеркивание; + + Remarks: + Remarks: + + Remove 'return' Удалить "return" @@ -241,6 +253,11 @@ Dash underline; Переименовать "{0}" в "_" + + Returns: + Returns: + + Simplify name Упростить имя diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.tr.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.tr.xlf index e6e9332dc33..d720dc43d7d 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.tr.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.tr.xlf @@ -22,6 +22,11 @@ 'new' anahtar sözcüğünü ekleme + + Add return type annotation + Add return type annotation + + Add type annotation Tür ek açıklaması ekle @@ -36,6 +41,7 @@ Inline hints; Display inline type hints (preview); Display return type hints (preview); Display inline parameter name hints (preview); +Use Transparent Compiler (experimental); Live Buffers; Use live (unsaved) buffers for analysis Blok Yapısı Kılavuzları; @@ -195,8 +201,9 @@ Navigation links; Show navigation links as; Solid underline; Dot underline; -Dash underline; - Biçimlendirme; +Dash underline; +Show remarks in Quick Info + Biçimlendirme; Karakter olarak tercih edilen açıklama genişliği; F# söz dizimi kurallarına uyan satır sonları ekleyerek imzayı verilen genişliğe biçimlendir; Gezinti bağlantıları; @@ -206,6 +213,11 @@ Nokta alt çizgi; Tire alt çizgisi; + + Remarks: + Remarks: + + Remove 'return' 'return' öğesini kaldır @@ -241,6 +253,11 @@ Tire alt çizgisi; '{0}' öğesini '_' olarak yeniden adlandırma + + Returns: + Returns: + + Simplify name Adı basitleştirme diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hans.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hans.xlf index 6df4f779a61..43eaadf6593 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hans.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hans.xlf @@ -22,6 +22,11 @@ 添加“新”关键字 + + Add return type annotation + Add return type annotation + + Add type annotation 添加类型注释 @@ -36,6 +41,7 @@ Inline hints; Display inline type hints (preview); Display return type hints (preview); Display inline parameter name hints (preview); +Use Transparent Compiler (experimental); Live Buffers; Use live (unsaved) buffers for analysis 块结构指南; @@ -195,8 +201,9 @@ Navigation links; Show navigation links as; Solid underline; Dot underline; -Dash underline; - 格式设置; +Dash underline; +Show remarks in Quick Info + 格式设置; 首选描述宽度 (以字符为单位); 通过添加符合 F# 语法规则的换行符,将签名格式设置为指定宽度; 导航链接; @@ -206,6 +213,11 @@ Dash underline; 短划线下划线; + + Remarks: + Remarks: + + Remove 'return' 删除 "return" @@ -241,6 +253,11 @@ Dash underline; 将“{0}”重命名为“_” + + Returns: + Returns: + + Simplify name 简化名称 diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hant.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hant.xlf index d270271bb75..96f071fb27e 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hant.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hant.xlf @@ -22,6 +22,11 @@ 新增 'new' 關鍵字 + + Add return type annotation + Add return type annotation + + Add type annotation 新增型別註解 @@ -36,6 +41,7 @@ Inline hints; Display inline type hints (preview); Display return type hints (preview); Display inline parameter name hints (preview); +Use Transparent Compiler (experimental); Live Buffers; Use live (unsaved) buffers for analysis 區塊結構輔助線; @@ -195,8 +201,9 @@ Navigation links; Show navigation links as; Solid underline; Dot underline; -Dash underline; - 格式化; +Dash underline; +Show remarks in Quick Info + 格式化; 慣用描述寬度 (以字元為單位); 透過新增符合 F# 語法規則的分行符號,將簽章格式設定為指定寬度; 瀏覽連結; @@ -206,6 +213,11 @@ Dash underline; 虛線底線; + + Remarks: + Remarks: + + Remove 'return' 移除 'return' @@ -241,6 +253,11 @@ Dash underline; 將 '{0}' 重新命名為 '_' + + Returns: + Returns: + + Simplify name 簡化名稱 diff --git a/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml b/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml index ecabe2a56fd..15397d068ec 100644 --- a/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml +++ b/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml @@ -38,6 +38,17 @@ + + + + diff --git a/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml b/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml index 96b8915b80e..a5c5f1c0b6f 100644 --- a/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml +++ b/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml @@ -23,6 +23,28 @@ IsChecked="{Binding EnableInMemoryCrossProjectReferences}" Content="{x:Static local:Strings.Enable_in_memory_cross_project_references}" ToolTip="{x:Static local:Strings.Tooltip_in_memory_cross_project_references}"/> + + + + + + @@ -46,7 +68,7 @@ Content="{x:Static local:Strings.Time_until_stale_completion}" Margin="15 0 0 0"/> diff --git a/vsintegration/src/FSharp.UIResources/QuickInfoOptionControl.xaml b/vsintegration/src/FSharp.UIResources/QuickInfoOptionControl.xaml index 528aa32b1cf..6b7c6531f48 100644 --- a/vsintegration/src/FSharp.UIResources/QuickInfoOptionControl.xaml +++ b/vsintegration/src/FSharp.UIResources/QuickInfoOptionControl.xaml @@ -1,16 +1,19 @@ - + - + @@ -20,21 +23,36 @@ - + - - - - + + + + + + + diff --git a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs index a7bcaa08413..b166f234ccd 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs +++ b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs @@ -474,6 +474,15 @@ public static string Show_Outlining { } } + /// + /// Looks up a localized string similar to Show remarks in Quick Info. + /// + public static string Show_remarks_in_Quick_Info { + get { + return ResourceManager.GetString("Show_remarks_in_Quick_Info", resourceCulture); + } + } + /// /// Looks up a localized string similar to Display return type hints (preview). /// @@ -546,6 +555,69 @@ public static string Tooltip_preferred_description_width_in_characters { } } + /// + /// Looks up a localized string similar to Transparent Compiler Cache Factor. + /// + public static string Transparent_Compiler_Cache_Factor { + get { + return ResourceManager.GetString("Transparent_Compiler_Cache_Factor", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Higher number means more memory will be used for caching. Changing the value wipes cache.. + /// + public static string Transparent_Compiler_Cache_Factor_Tooltip { + get { + return ResourceManager.GetString("Transparent_Compiler_Cache_Factor_Tooltip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create new project snapshots from existing ones. + /// + public static string Transparent_Compiler_Snapshot_Reuse { + get { + return ResourceManager.GetString("Transparent_Compiler_Snapshot_Reuse", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Transparent Compiler (experimental). + /// + public static string TransparentCompiler { + get { + return ResourceManager.GetString("TransparentCompiler", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results.. + /// + public static string TransparentCompiler_Discalimer1 { + get { + return ResourceManager.GetString("TransparentCompiler_Discalimer1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use at your own risk!. + /// + public static string TransparentCompiler_Discalimer2 { + get { + return ResourceManager.GetString("TransparentCompiler_Discalimer2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to By checking this you also opt-in for additional performance telemetry. + /// + public static string TransparentCompiler_Discalimer3 { + get { + return ResourceManager.GetString("TransparentCompiler_Discalimer3", resourceCulture); + } + } + /// /// Looks up a localized string similar to Analyze and suggest fixes for unused values. /// @@ -572,5 +644,14 @@ public static string Use_syntax_tree_cache { return ResourceManager.GetString("Use_syntax_tree_cache", resourceCulture); } } + + /// + /// Looks up a localized string similar to Use Transparent Compiler (restart required). + /// + public static string Use_Transparent_Compiler { + get { + return ResourceManager.GetString("Use_Transparent_Compiler", resourceCulture); + } + } } } diff --git a/vsintegration/src/FSharp.UIResources/Strings.resx b/vsintegration/src/FSharp.UIResources/Strings.resx index b1362651cb3..58821d8b8be 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.resx +++ b/vsintegration/src/FSharp.UIResources/Strings.resx @@ -279,13 +279,40 @@ Display return type hints (preview) + + Transparent Compiler (experimental) + + + Use Transparent Compiler (restart required) + Keep analyzing the entire solution for diagnostics as a low priority background task (requires restart) Background analysis + + Transparent Compiler Cache Factor + + + Higher number means more memory will be used for caching. Changing the value wipes cache. + Remove unnecessary parentheses (experimental, might affect typing performance) + + Show remarks in Quick Info + + + Create new project snapshots from existing ones + + + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + + + Use at your own risk! + + + By checking this you also opt-in for additional performance telemetry + \ No newline at end of file diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf index 4c1afb7bca0..c0072448173 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf @@ -34,7 +34,7 @@ Use live (unsaved) buffers for analysis (restart required) - Pro kontrolu používat živé (neuložené) vyrovnávací paměti (vyžaduje se restartování) + Pro analýzu používat živé (neuložené) vyrovnávací paměti (vyžaduje se restartování) @@ -109,7 +109,7 @@ Live Buffers - Živé vyrovnávací paměti (experimentální) + Živé vyrovnávací paměti @@ -129,7 +129,7 @@ Remove unnecessary parentheses (experimental, might affect typing performance) - Remove unnecessary parentheses (experimental, might affect typing performance) + Odebrání nepotřebných závorek (experimentální, může mít vliv na výkon při psaní) @@ -177,6 +177,11 @@ Zo_brazit navigační odkazy jako + + Show remarks in Quick Info + Zobrazit poznámky v Rychlých informacích + + Simplify names (remove unnecessary qualifiers) Zjednodušit názvy (odebrat nepotřebné kvalifikátory) @@ -197,6 +202,41 @@ Umožňuje formátovat podpis na danou šířku přidáním konců řádků odpovídajících pravidlům syntaxe F#. + + Transparent Compiler (experimental) + Transparent Compiler (experimental) + + + + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + + + + Use at your own risk! + Use at your own risk! + + + + By checking this you also opt-in for additional performance telemetry + By checking this you also opt-in for additional performance telemetry + + + + Transparent Compiler Cache Factor + Transparent Compiler Cache Factor + + + + Higher number means more memory will be used for caching. Changing the value wipes cache. + Higher number means more memory will be used for caching. Changing the value wipes cache. + + + + Create new project snapshots from existing ones + Create new project snapshots from existing ones + + Remove unused open statements Odebrat nepoužívané otevřené výkazy @@ -282,6 +322,11 @@ Navrhovat názvy pro nerozpoznané identifikátory + + Use Transparent Compiler (restart required) + Use Transparent Compiler (restart required) + + Cache parsing results (experimental) Výsledky analýzy mezipaměti (experimentální) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf index f93c85b0afc..8afb1d8e999 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf @@ -34,7 +34,7 @@ Use live (unsaved) buffers for analysis (restart required) - Livepuffer (nicht gespeichert) zur Überprüfung verwenden (Neustart erforderlich) + Livepuffer (nicht gespeichert) zur Analyse verwenden (Neustart erforderlich) @@ -109,7 +109,7 @@ Live Buffers - Livepuffer (experimentell) + Livepuffer @@ -129,7 +129,7 @@ Remove unnecessary parentheses (experimental, might affect typing performance) - Remove unnecessary parentheses (experimental, might affect typing performance) + Entfernen unnötiger Klammern (experimentell, kann sich auf die Eingabeleistung auswirken) @@ -177,6 +177,11 @@ Navigationslink_s anzeigen als + + Show remarks in Quick Info + Hinweise in QuickInfo anzeigen + + Simplify names (remove unnecessary qualifiers) Namen vereinfachen (unnötige Qualifizierer entfernen) @@ -197,6 +202,41 @@ Formatieren Sie die Signatur in der angegebenen Breite, indem Sie Zeilenumbrüche hinzufügen, die F#-Syntaxregeln entsprechen. + + Transparent Compiler (experimental) + Transparent Compiler (experimental) + + + + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + + + + Use at your own risk! + Use at your own risk! + + + + By checking this you also opt-in for additional performance telemetry + By checking this you also opt-in for additional performance telemetry + + + + Transparent Compiler Cache Factor + Transparent Compiler Cache Factor + + + + Higher number means more memory will be used for caching. Changing the value wipes cache. + Higher number means more memory will be used for caching. Changing the value wipes cache. + + + + Create new project snapshots from existing ones + Create new project snapshots from existing ones + + Remove unused open statements Nicht verwendete "open"-Anweisungen entfernen @@ -282,6 +322,11 @@ Namen für nicht aufgelöste Bezeichner vorschlagen + + Use Transparent Compiler (restart required) + Use Transparent Compiler (restart required) + + Cache parsing results (experimental) Cacheanalyseergebnisse (experimentell) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf index 3b65a70284b..eb0289c938c 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf @@ -34,7 +34,7 @@ Use live (unsaved) buffers for analysis (restart required) - Utilizar buffers activos (no guardados) para la comprobación (es necesario reiniciar) + Utilizar buffers activos (no guardados) para el análisis (es necesario reiniciar) @@ -109,7 +109,7 @@ Live Buffers - Búferes activos (experimental) + Búferes activos @@ -129,7 +129,7 @@ Remove unnecessary parentheses (experimental, might affect typing performance) - Remove unnecessary parentheses (experimental, might affect typing performance) + Quitar paréntesis innecesarios (experimental, puede afectar al rendimiento de escritura) @@ -177,6 +177,11 @@ M_ostrar vínculos de navegación como + + Show remarks in Quick Info + Mostrar comentarios en Información rápida + + Simplify names (remove unnecessary qualifiers) Simplificar nombres (quitar calificadores innecesarios) @@ -197,6 +202,41 @@ Da formato a la firma al ancho dado agregando saltos de línea conforme a las reglas de sintaxis de F#. + + Transparent Compiler (experimental) + Transparent Compiler (experimental) + + + + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + + + + Use at your own risk! + Use at your own risk! + + + + By checking this you also opt-in for additional performance telemetry + By checking this you also opt-in for additional performance telemetry + + + + Transparent Compiler Cache Factor + Transparent Compiler Cache Factor + + + + Higher number means more memory will be used for caching. Changing the value wipes cache. + Higher number means more memory will be used for caching. Changing the value wipes cache. + + + + Create new project snapshots from existing ones + Create new project snapshots from existing ones + + Remove unused open statements Quitar instrucciones open no usadas @@ -282,6 +322,11 @@ Sugerir nombres para los identificadores no resueltos + + Use Transparent Compiler (restart required) + Use Transparent Compiler (restart required) + + Cache parsing results (experimental) Resultados del análisis de la caché (experimental) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf index 1fcb58d38a5..09430b644cc 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf @@ -34,7 +34,7 @@ Use live (unsaved) buffers for analysis (restart required) - Utiliser des tampons en direct (non enregistrés) pour la vérification (redémarrage requis) + Utiliser des tampons en direct (non enregistrés) pour l’analysye (redémarrage requis) @@ -109,7 +109,7 @@ Live Buffers - Live Buffers (expérimental) + Tampons en direct @@ -129,7 +129,7 @@ Remove unnecessary parentheses (experimental, might affect typing performance) - Remove unnecessary parentheses (experimental, might affect typing performance) + Supprimer les parenthèses inutiles (expérimental, peut affecter les performances de saisie) @@ -177,6 +177,11 @@ Affic_her les liens de navigation en tant que + + Show remarks in Quick Info + Afficher les notes dans Info express + + Simplify names (remove unnecessary qualifiers) Simplifier les noms (supprimer les qualificateurs inutiles) @@ -197,6 +202,41 @@ Formatez la signature à la largeur donnée en ajoutant des sauts de ligne conformes aux règles de syntaxe F#. + + Transparent Compiler (experimental) + Transparent Compiler (experimental) + + + + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + + + + Use at your own risk! + Use at your own risk! + + + + By checking this you also opt-in for additional performance telemetry + By checking this you also opt-in for additional performance telemetry + + + + Transparent Compiler Cache Factor + Transparent Compiler Cache Factor + + + + Higher number means more memory will be used for caching. Changing the value wipes cache. + Higher number means more memory will be used for caching. Changing the value wipes cache. + + + + Create new project snapshots from existing ones + Create new project snapshots from existing ones + + Remove unused open statements Supprimer les instructions open inutilisées @@ -282,6 +322,11 @@ Suggérer des noms pour les identificateurs non résolus + + Use Transparent Compiler (restart required) + Use Transparent Compiler (restart required) + + Cache parsing results (experimental) Résultats de l'analyse du cache (expérimental) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf index ac84a49ac04..640894aac42 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf @@ -34,7 +34,7 @@ Use live (unsaved) buffers for analysis (restart required) - Usa buffer in tempo reale (non salvati) per il controllo (riavvio necessario) + Usa buffer in tempo reale (non salvati) per l’analisi (riavvio necessario) @@ -109,7 +109,7 @@ Live Buffers - Buffer in tempo reale (sperimentale) + Buffer in tempo reale @@ -129,7 +129,7 @@ Remove unnecessary parentheses (experimental, might affect typing performance) - Remove unnecessary parentheses (experimental, might affect typing performance) + Rimuovi le parentesi non necessarie (sperimentale, potrebbe influire sulle prestazioni di digitazione) @@ -177,6 +177,11 @@ M_ostra collegamenti di navigazione come + + Show remarks in Quick Info + Mostra i commenti in Informazioni rapide + + Simplify names (remove unnecessary qualifiers) Semplifica nomi (rimuovi qualificatori non necessari) @@ -197,6 +202,41 @@ Consente di formattare la firma in base alla larghezza specificata aggiungendo interruzioni di riga conformi alle regole di sintassi F#. + + Transparent Compiler (experimental) + Transparent Compiler (experimental) + + + + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + + + + Use at your own risk! + Use at your own risk! + + + + By checking this you also opt-in for additional performance telemetry + By checking this you also opt-in for additional performance telemetry + + + + Transparent Compiler Cache Factor + Transparent Compiler Cache Factor + + + + Higher number means more memory will be used for caching. Changing the value wipes cache. + Higher number means more memory will be used for caching. Changing the value wipes cache. + + + + Create new project snapshots from existing ones + Create new project snapshots from existing ones + + Remove unused open statements Rimuovi istruzioni OPEN inutilizzate @@ -282,6 +322,11 @@ Suggerisci nomi per gli identificatori non risolti + + Use Transparent Compiler (restart required) + Use Transparent Compiler (restart required) + + Cache parsing results (experimental) Risultati dell'analisi della cache (sperimentale) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf index 76036894dcb..7267c7b7061 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf @@ -34,7 +34,7 @@ Use live (unsaved) buffers for analysis (restart required) - ライブ (未保存) バッファーをチェックに使用する (再起動が必要) + ライブ (未保存) バッファーをチェックに使用する (再起動が必要) @@ -109,7 +109,7 @@ Live Buffers - ライブ バッファー (試験段階) + ライブ バッファー @@ -129,7 +129,7 @@ Remove unnecessary parentheses (experimental, might affect typing performance) - Remove unnecessary parentheses (experimental, might affect typing performance) + 不要なかっこを削除します (試験段階であり、入力のパフォーマンスに影響する可能性があります) @@ -177,6 +177,11 @@ 次としてナビゲーション リンクを表示する(_H) + + Show remarks in Quick Info + クイック ヒントに注釈を表示する + + Simplify names (remove unnecessary qualifiers) 名前の簡略化する (不要な修飾子の削除) @@ -197,6 +202,41 @@ F# 構文規則に準拠した改行を追加して、署名を指定された幅に書式設定します。 + + Transparent Compiler (experimental) + Transparent Compiler (experimental) + + + + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + + + + Use at your own risk! + Use at your own risk! + + + + By checking this you also opt-in for additional performance telemetry + By checking this you also opt-in for additional performance telemetry + + + + Transparent Compiler Cache Factor + Transparent Compiler Cache Factor + + + + Higher number means more memory will be used for caching. Changing the value wipes cache. + Higher number means more memory will be used for caching. Changing the value wipes cache. + + + + Create new project snapshots from existing ones + Create new project snapshots from existing ones + + Remove unused open statements 未使用の Open ステートメントを削除する @@ -282,6 +322,11 @@ 未解決の識別子の名前を提案します + + Use Transparent Compiler (restart required) + Use Transparent Compiler (restart required) + + Cache parsing results (experimental) キャッシュ解析の結果 (試験段階) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf index f166bba08f3..cfb0da2f9b4 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf @@ -34,7 +34,7 @@ Use live (unsaved) buffers for analysis (restart required) - 확인에 라이브(저장되지 않은) 버퍼 사용(다시 시작 필요) + 분석에 라이브(저장되지 않은) 버퍼 사용(다시 시작 필요) @@ -109,7 +109,7 @@ Live Buffers - 라이브 버퍼(실험적) + 라이브 버퍼 @@ -129,7 +129,7 @@ Remove unnecessary parentheses (experimental, might affect typing performance) - Remove unnecessary parentheses (experimental, might affect typing performance) + 불필요한 괄호 제거(실험적, 입력 성능에 영향을 줄 수 있음) @@ -177,6 +177,11 @@ 탐색 링크를 다음으로 표시(_H) + + Show remarks in Quick Info + 요약 정보에 설명 표시 + + Simplify names (remove unnecessary qualifiers) 이름 단순화(불필요한 한정자 제거) @@ -197,6 +202,41 @@ F# 구문 규칙에 맞는 줄 바꿈을 추가하여 지정된 너비에 시그니처의 서식을 지정합니다. + + Transparent Compiler (experimental) + Transparent Compiler (experimental) + + + + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + + + + Use at your own risk! + Use at your own risk! + + + + By checking this you also opt-in for additional performance telemetry + By checking this you also opt-in for additional performance telemetry + + + + Transparent Compiler Cache Factor + Transparent Compiler Cache Factor + + + + Higher number means more memory will be used for caching. Changing the value wipes cache. + Higher number means more memory will be used for caching. Changing the value wipes cache. + + + + Create new project snapshots from existing ones + Create new project snapshots from existing ones + + Remove unused open statements 사용되지 않는 open 문 제거 @@ -282,6 +322,11 @@ 확인되지 않은 식별자의 이름 제안 + + Use Transparent Compiler (restart required) + Use Transparent Compiler (restart required) + + Cache parsing results (experimental) 캐시 구문 분석 결과(실험적) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf index c4d70ab3a1f..4fb4ff03b40 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf @@ -34,7 +34,7 @@ Use live (unsaved) buffers for analysis (restart required) - Użyj aktywnych (niezapisanych) buforów do sprawdzania (wymagane ponowne uruchomienie) + Użyj bieżących (niezapisanych) buforów do analizy (wymagane ponowne uruchomienie) @@ -109,7 +109,7 @@ Live Buffers - Aktywne bufory (eksperymentalne) + Bufory bieżące @@ -129,7 +129,7 @@ Remove unnecessary parentheses (experimental, might affect typing performance) - Remove unnecessary parentheses (experimental, might affect typing performance) + Usuń niepotrzebne nawiasy (eksperymentalne, może to wpłynąć na wydajność pisania) @@ -177,6 +177,11 @@ P_okaż linki nawigacyjne jako + + Show remarks in Quick Info + Pokaż uwagi w szybkich podpowiedziach + + Simplify names (remove unnecessary qualifiers) Uprość nazwy (usuń niepotrzebne kwalifikatory) @@ -197,6 +202,41 @@ Sformatuj sygnaturę na daną szerokość, dodając podziały wierszy zgodne z regułami składni języka F#. + + Transparent Compiler (experimental) + Transparent Compiler (experimental) + + + + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + + + + Use at your own risk! + Use at your own risk! + + + + By checking this you also opt-in for additional performance telemetry + By checking this you also opt-in for additional performance telemetry + + + + Transparent Compiler Cache Factor + Transparent Compiler Cache Factor + + + + Higher number means more memory will be used for caching. Changing the value wipes cache. + Higher number means more memory will be used for caching. Changing the value wipes cache. + + + + Create new project snapshots from existing ones + Create new project snapshots from existing ones + + Remove unused open statements Usuń nieużywane otwarte instrukcje @@ -282,6 +322,11 @@ Sugeruj nazwy w przypadku nierozpoznanych identyfikatorów + + Use Transparent Compiler (restart required) + Use Transparent Compiler (restart required) + + Cache parsing results (experimental) Wyniki analizy pamięci podręcznej (eksperymentalne) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf index f1ef03e827e..f2778bcbd8b 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf @@ -34,7 +34,7 @@ Use live (unsaved) buffers for analysis (restart required) - Usar buffers dinâmicos (não salvos) para verificação (reinicialização necessária) + Usar buffers dinâmicos (não salvos) para verificação (reinicialização necessária) @@ -109,7 +109,7 @@ Live Buffers - Buffers Dinâmicos (experimental) + Buffers Dinâmicos @@ -129,7 +129,7 @@ Remove unnecessary parentheses (experimental, might affect typing performance) - Remove unnecessary parentheses (experimental, might affect typing performance) + Remover parênteses desnecessários (experimental, pode afetar o desempenho da digitação) @@ -177,6 +177,11 @@ E_xibir link de navegação como + + Show remarks in Quick Info + Mostrar os comentários nas Informações Rápidas + + Simplify names (remove unnecessary qualifiers) Simplificar nomes (remover qualificadores desnecessários) @@ -197,6 +202,41 @@ Formate a assinatura para a largura fornecida adicionando quebras de linha em conformidade com as regras de sintaxe F#. + + Transparent Compiler (experimental) + Transparent Compiler (experimental) + + + + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + + + + Use at your own risk! + Use at your own risk! + + + + By checking this you also opt-in for additional performance telemetry + By checking this you also opt-in for additional performance telemetry + + + + Transparent Compiler Cache Factor + Transparent Compiler Cache Factor + + + + Higher number means more memory will be used for caching. Changing the value wipes cache. + Higher number means more memory will be used for caching. Changing the value wipes cache. + + + + Create new project snapshots from existing ones + Create new project snapshots from existing ones + + Remove unused open statements Remover instruções abertas não usadas @@ -282,6 +322,11 @@ Sugerir nomes para identificadores não resolvidos + + Use Transparent Compiler (restart required) + Use Transparent Compiler (restart required) + + Cache parsing results (experimental) Resultados da análise de cache (experimental) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf index 4db5610e9bb..9b99816b43c 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf @@ -34,7 +34,7 @@ Use live (unsaved) buffers for analysis (restart required) - Использовать динамические (несохраненные) буферы для проверки (требуется перезагрузка) + Используйте для анализа живые (несохраненные) буферы (требуется перезагрузка) @@ -109,7 +109,7 @@ Live Buffers - Динамические буферы (экспериментальная функция) + Живые буферы @@ -129,7 +129,7 @@ Remove unnecessary parentheses (experimental, might affect typing performance) - Remove unnecessary parentheses (experimental, might affect typing performance) + Удалите ненужные круглые скобки (экспериментально, может повлиять на производительность набора текста) @@ -177,6 +177,11 @@ П_оказать ссылки навигации как + + Show remarks in Quick Info + Показать заметки в кратких сведениях + + Simplify names (remove unnecessary qualifiers) Упростить имена (удалить ненужные квалификаторы) @@ -197,6 +202,41 @@ Форматирование подписи до заданной ширины путем добавления разрывов строк, соответствующих правилам синтаксиса F#. + + Transparent Compiler (experimental) + Transparent Compiler (experimental) + + + + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + + + + Use at your own risk! + Use at your own risk! + + + + By checking this you also opt-in for additional performance telemetry + By checking this you also opt-in for additional performance telemetry + + + + Transparent Compiler Cache Factor + Transparent Compiler Cache Factor + + + + Higher number means more memory will be used for caching. Changing the value wipes cache. + Higher number means more memory will be used for caching. Changing the value wipes cache. + + + + Create new project snapshots from existing ones + Create new project snapshots from existing ones + + Remove unused open statements Удалить неиспользуемые открытые операторы @@ -282,6 +322,11 @@ Предлагать имена для неразрешенных идентификаторов + + Use Transparent Compiler (restart required) + Use Transparent Compiler (restart required) + + Cache parsing results (experimental) Результаты анализа кэша (экспериментальная функция) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf index 95fa383de7e..e6afdd2e2b1 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf @@ -34,7 +34,7 @@ Use live (unsaved) buffers for analysis (restart required) - Denetim için canlı (kaydedilmemiş) arabellekler kullanın (yeniden başlatma gerekir) + Analiz için canlı (kaydedilmemiş) arabellekleri kullan (yeniden başlatma gerekir) @@ -109,7 +109,7 @@ Live Buffers - Canlı Arabellekler (deneysel) + Canlı Arabellekler @@ -129,7 +129,7 @@ Remove unnecessary parentheses (experimental, might affect typing performance) - Remove unnecessary parentheses (experimental, might affect typing performance) + Gereksiz parantezleri kaldır (deneysel, yazma performansını etkileyebilir) @@ -177,6 +177,11 @@ Gezinti bağlantılarını farklı _göster + + Show remarks in Quick Info + Hızlı Bilgi notlarını göster + + Simplify names (remove unnecessary qualifiers) Adları basitleştir (gereksiz niteleyicileri kaldır) @@ -197,6 +202,41 @@ F# söz dizimi kurallarına uyan satır sonları ekleyerek imzayı belirtilen genişliğe biçimlendirin. + + Transparent Compiler (experimental) + Transparent Compiler (experimental) + + + + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + + + + Use at your own risk! + Use at your own risk! + + + + By checking this you also opt-in for additional performance telemetry + By checking this you also opt-in for additional performance telemetry + + + + Transparent Compiler Cache Factor + Transparent Compiler Cache Factor + + + + Higher number means more memory will be used for caching. Changing the value wipes cache. + Higher number means more memory will be used for caching. Changing the value wipes cache. + + + + Create new project snapshots from existing ones + Create new project snapshots from existing ones + + Remove unused open statements Kullanılmayan açık deyimleri kaldır @@ -282,6 +322,11 @@ Çözümlenmemiş tanımlayıcılar için ad öner + + Use Transparent Compiler (restart required) + Use Transparent Compiler (restart required) + + Cache parsing results (experimental) Ayrıştırma sonuçlarını önbelleğe al (deneysel) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf index 3b45fdaf529..9bd919f4b51 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf @@ -34,7 +34,7 @@ Use live (unsaved) buffers for analysis (restart required) - 使用实时(未保存)缓冲区进行检查(需要重新启动) + 使用实时(未保存)缓冲区进行分析(需要重新启动) @@ -109,7 +109,7 @@ Live Buffers - 实时缓冲区(实验性) + 实时缓冲区 @@ -129,7 +129,7 @@ Remove unnecessary parentheses (experimental, might affect typing performance) - Remove unnecessary parentheses (experimental, might affect typing performance) + 删除不必要的括号(实验性,可能会影响键入性能) @@ -177,6 +177,11 @@ 导航链接显示方式(_H) + + Show remarks in Quick Info + 在快速信息中显示备注 + + Simplify names (remove unnecessary qualifiers) 简化名称(删除不必要的限定符) @@ -197,6 +202,41 @@ 通过添加符合 F# 语法规则的换行符,将签名设置为给定宽度的格式。 + + Transparent Compiler (experimental) + Transparent Compiler (experimental) + + + + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + + + + Use at your own risk! + Use at your own risk! + + + + By checking this you also opt-in for additional performance telemetry + By checking this you also opt-in for additional performance telemetry + + + + Transparent Compiler Cache Factor + Transparent Compiler Cache Factor + + + + Higher number means more memory will be used for caching. Changing the value wipes cache. + Higher number means more memory will be used for caching. Changing the value wipes cache. + + + + Create new project snapshots from existing ones + Create new project snapshots from existing ones + + Remove unused open statements 删除未使用的 open 语句 @@ -282,6 +322,11 @@ 为未解析标识符建议名称 + + Use Transparent Compiler (restart required) + Use Transparent Compiler (restart required) + + Cache parsing results (experimental) 缓存分析结果(实验性) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf index 50aede6ee96..d537c05ffd2 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf @@ -34,7 +34,7 @@ Use live (unsaved) buffers for analysis (restart required) - 使用即時 (未儲存) 緩衝區進行檢查 (需要重新啟動) + 使用即時 (未儲存) 緩衝區進行分析 (需要重新啟動) @@ -109,7 +109,7 @@ Live Buffers - 即時緩衝區 (實驗性) + 即時緩衝區 @@ -129,7 +129,7 @@ Remove unnecessary parentheses (experimental, might affect typing performance) - Remove unnecessary parentheses (experimental, might affect typing performance) + 移除實驗性 (不必要的括弧,可能會影響輸入效能) @@ -177,6 +177,11 @@ 顯示導覽連結為(_H) + + Show remarks in Quick Info + 在快速諮詢中顯示備註 + + Simplify names (remove unnecessary qualifiers) 簡化名稱 (移除不必要的限定詞) @@ -197,6 +202,41 @@ 透過新增符合 F# 語法規則的分行符號,將簽章格式設定為指定寬度。 + + Transparent Compiler (experimental) + Transparent Compiler (experimental) + + + + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. + + + + Use at your own risk! + Use at your own risk! + + + + By checking this you also opt-in for additional performance telemetry + By checking this you also opt-in for additional performance telemetry + + + + Transparent Compiler Cache Factor + Transparent Compiler Cache Factor + + + + Higher number means more memory will be used for caching. Changing the value wipes cache. + Higher number means more memory will be used for caching. Changing the value wipes cache. + + + + Create new project snapshots from existing ones + Create new project snapshots from existing ones + + Remove unused open statements 移除未使用的 open 陳述式 @@ -282,6 +322,11 @@ 為未解析的識別碼建議名稱 + + Use Transparent Compiler (restart required) + Use Transparent Compiler (restart required) + + Cache parsing results (experimental) 快取剖析結果 (實驗性) diff --git a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveUnnecessaryParenthesesTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveUnnecessaryParenthesesTests.fs index 8b9a4116264..69d6456e378 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveUnnecessaryParenthesesTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveUnnecessaryParenthesesTests.fs @@ -616,7 +616,8 @@ in x "([] : int list).Length", "([] : int list).Length" // DotLambda - "[{| A = x |}] |> List.map (_.A)", "[{| A = x |}] |> List.map _.A" + """_.ToString("x")""", """_.ToString("x")""" + """_.ToString(("x"))""", """_.ToString("x")""" // DotSet "(ref 3).Value <- (3)", "(ref 3).Value <- 3" @@ -1078,7 +1079,7 @@ in x |> id " - "x |> (id |> fun x -> x)", "x |> id |> fun x -> x" + "x |> (id |> fun x -> x)", "x |> (id |> fun x -> x)" "x |> (id <| fun x -> x)", "x |> (id <| fun x -> x)" "id <| (fun x -> x)", "id <| fun x -> x" "id <| (fun x -> x) |> id", "id <| (fun x -> x) |> id" @@ -1120,6 +1121,10 @@ in x "id (-(-x))", "id -(-x)" "id -(-x)", "id -(-x)" + "f <| (g << h)", "f <| (g << h)" + "x <> (y <> z)", "x <> (y <> z)" + "x > (y > z)", "x > (y > z)" + " let f x y = 0 f ((+) x y) z @@ -1191,6 +1196,8 @@ in x // DotLambda "[{| A = x |}] |> List.map (_.A)", "[{| A = x |}] |> List.map _.A" + """[1..10] |> List.map _.ToString("x")""", """[1..10] |> List.map _.ToString("x")""" + """[1..10] |> List.map _.ToString(("x"))""", """[1..10] |> List.map _.ToString("x")""" // DotSet "id ((ref x).Value <- y)", "id ((ref x).Value <- y)" @@ -1423,6 +1430,12 @@ let _ = (2 + 2) { return 5 } /// (x λ y) ρ z | OuterRight of l: string * r: string + /// Indicates whether both operators are the same exact symbolic operator. + member this.Identical = + match this with + | OuterLeft(l, r) + | OuterRight(l, r) -> l = r + override this.ToString() = match this with | OuterLeft(l, r) -> $"x {l} (y {r} z)" @@ -1471,11 +1484,11 @@ let _ = (2 + 2) { return 5 } | OuterLeft((":?" | ":>" | ":?>"), _) -> invalidPairing | OuterLeft(_, "**op") -> fixable pair | OuterLeft("**op", _) -> unfixable pair - | OuterLeft("*op", "*op") -> fixable pair + | OuterLeft("*op", "*op") -> if pair.Identical then fixable pair else unfixable pair | OuterLeft(("%op" | "/op" | "*op"), ("%op" | "/op" | "*op")) -> unfixable pair | OuterLeft(_, ("%op" | "/op" | "*op")) -> fixable pair | OuterLeft(("%op" | "/op" | "*op"), _) -> unfixable pair - | OuterLeft("+op", "+op") -> fixable pair + | OuterLeft("+op", "+op") -> if pair.Identical then fixable pair else unfixable pair | OuterLeft(("-op" | "+op"), ("-op" | "+op")) -> unfixable pair | OuterLeft(_, ("-op" | "+op")) -> fixable pair | OuterLeft(("-op" | "+op"), _) -> unfixable pair @@ -1484,14 +1497,15 @@ let _ = (2 + 2) { return 5 } | OuterLeft("::", _) -> unfixable pair | OuterLeft(_, ("^op" | "@op")) -> fixable pair | OuterLeft(("^op" | "@op"), _) -> unfixable pair - | OuterLeft(l & ("=op" | "|op" | "&op" | "$" | ">op" | "op" | " - if l = r then fixable pair else unfixable pair + | OuterLeft(("=op" | "|op" | "&op" | "$" | ">op" | "op" | " unfixable pair | OuterLeft(_, ("=op" | "|op" | "&op" | "$" | ">op" | " fixable pair | OuterLeft(("=op" | "|op" | "&op" | "$" | ">op" | " unfixable pair | OuterLeft(_, (":>" | ":?>")) -> fixable pair + | OuterLeft(("&" | "&&"), ("&" | "&&")) -> if pair.Identical then fixable pair else unfixable pair | OuterLeft(_, ("&" | "&&")) -> fixable pair | OuterLeft(("&" | "&&"), _) -> unfixable pair + | OuterLeft(("||" | "or"), ("||" | "or")) -> if pair.Identical then fixable pair else unfixable pair | OuterLeft(_, ("||" | "or")) -> fixable pair | OuterLeft(("||" | "or"), _) -> unfixable pair | OuterLeft(":=", ":=") -> fixable pair @@ -1524,11 +1538,14 @@ let _ = (2 + 2) { return 5 } let operators = [ "**" + "***" "*" + "*." "/" "%" "-" "+" + "++" ":?" "::" "^^^" diff --git a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj index 77ce57f27e0..a180accc43f 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj +++ b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj @@ -12,6 +12,7 @@ + @@ -71,6 +72,8 @@ + + diff --git a/vsintegration/tests/FSharp.Editor.Tests/Helpers/RoslynHelpers.fs b/vsintegration/tests/FSharp.Editor.Tests/Helpers/RoslynHelpers.fs index a0853ed83b9..ca113f72bf3 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/Helpers/RoslynHelpers.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/Helpers/RoslynHelpers.fs @@ -304,6 +304,11 @@ type RoslynTestHelpers private () = let document = project.Documents |> Seq.exactlyOne document + static member GetLastDocument(solution: Solution) = + let project = solution.Projects |> Seq.exactlyOne + let document = project.Documents |> Seq.last + document + static member CreateSolution(syntheticProject: SyntheticProject) = let checker = syntheticProject.SaveAndCheck() diff --git a/vsintegration/tests/FSharp.Editor.Tests/QuickInfoTests.fs b/vsintegration/tests/FSharp.Editor.Tests/QuickInfoTests.fs index 083a25a07cf..8b24af5f117 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/QuickInfoTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/QuickInfoTests.fs @@ -50,12 +50,12 @@ module QuickInfo = | Some(ToolTipText elements) when not elements.IsEmpty -> let documentationBuilder = { new IDocumentationBuilder with - override _.AppendDocumentationFromProcessedXML(_, _, _, _, _, _) = () - override _.AppendDocumentation(_, _, _, _, _, _, _) = () + override _.AppendDocumentationFromProcessedXML(_, _, _, _, _, _, _) = () + override _.AppendDocumentation(_, _, _, _, _, _, _, _) = () } let _, mainDescription, docs = - XmlDocumentation.BuildSingleTipText(documentationBuilder, elements.Head, XmlDocumentation.DefaultLineLimits) + XmlDocumentation.BuildSingleTipText(documentationBuilder, elements.Head, XmlDocumentation.DefaultLineLimits, true) let mainTextItems = mainDescription |> Seq.map (fun x -> x.Text) let docTextItems = docs |> Seq.map (fun x -> x.Text) diff --git a/vsintegration/tests/FSharp.Editor.Tests/Refactors/AddReturnTypeTests.fs b/vsintegration/tests/FSharp.Editor.Tests/Refactors/AddReturnTypeTests.fs new file mode 100644 index 00000000000..5b81fb996da --- /dev/null +++ b/vsintegration/tests/FSharp.Editor.Tests/Refactors/AddReturnTypeTests.fs @@ -0,0 +1,452 @@ +module FSharp.Editor.Tests.Refactors.AddReturnTypeTests + +open Microsoft.VisualStudio.FSharp.Editor +open Xunit +open FSharp.Editor.Tests.Refactors.RefactorTestFramework +open FSharp.Test.ProjectGeneration +open FSharp.Editor.Tests.Helpers + +[] +[] +[] +[] +[] +let ``Refactor should not trigger`` (shouldNotTrigger: string) = + let symbolName = "sum" + + let code = + $""" +let sum a b {shouldNotTrigger}= a + b + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let actions = tryGetRefactoringActions code spanStart context (new AddReturnType()) + + do Assert.Empty(actions) + +[] +let ``Refactor should not trigger on values`` () = + let symbolName = "example2" + + let code = + """ +let example2 = 42 // value + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let actions = tryGetRefactoringActions code spanStart context (new AddReturnType()) + + do Assert.Empty(actions) + +[] +let ``Refactor should not trigger on member values`` () = + let symbolName = "SomeProp" + + let code = + """ +type Example3() = + member _.SomeProp = 42 // property + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let actions = tryGetRefactoringActions code spanStart context (new AddReturnType()) + + do Assert.Empty(actions) + +[] +let ``Correctly infer int as return type`` () = + let symbolName = "sum" + + let code = + """ +let sum a b = a + b + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let newDoc = tryRefactor code spanStart context (new AddReturnType()) + + let expectedCode = + $""" +let sum a b : int = a + b + """ + + let resultText = newDoc.GetTextAsync() |> GetTaskResult + Assert.Equal(expectedCode, resultText.ToString()) + +[] +let ``Correctly infer on next line arguments`` () = + let symbolName = "sum" + + let code = + """ +let sum + x y = + x + y + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let newDoc = tryRefactor code spanStart context (new AddReturnType()) + + let expectedCode = + $""" +let sum + x y : int = + x + y + """ + + let resultText = newDoc.GetTextAsync() |> GetTaskResult + Assert.Equal(expectedCode, resultText.ToString()) + +[] +let ``Should not throw exception when binding another method`` () = + let symbolName = "addThings" + + let code = + """ +let add (x:int) (y:int) = (float(x + y)) + 0.1 +let addThings = add + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let newDoc = tryRefactor code spanStart context (new AddReturnType()) + + let expectedCode = + $""" +let add (x:int) (y:int) = (float(x + y)) + 0.1 +let addThings : (int->int->float) = add + """ + + let resultText = newDoc.GetTextAsync() |> GetTaskResult + Assert.Equal(expectedCode, resultText.ToString()) + +[] +let ``Handle parantheses on the arguments`` () = + let symbolName = "sum" + + let code = + """ +let sum (a:float) (b:float) = a + b + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let newDoc = tryRefactor code spanStart context (new AddReturnType()) + + let expectedCode = + """ +let sum (a:float) (b:float) : float = a + b + """ + + let resultText = newDoc.GetTextAsync() |> GetTaskResult + Assert.Equal(expectedCode, resultText.ToString()) + +[] +let ``Infer on rec method`` () = + let symbolName = "fib" + + let code = + $""" +let rec fib n = + if n < 2 then 1 + else fib (n - 1) + fib (n - 2) + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let newDoc = tryRefactor code spanStart context (new AddReturnType()) + + let expectedCode = + $""" +let rec fib n : int = + if n < 2 then 1 + else fib (n - 1) + fib (n - 2) + """ + + let resultText = newDoc.GetTextAsync() |> GetTaskResult + Assert.Equal(expectedCode, resultText.ToString()) + +[] +let ``Infer with function parameter method`` () = + let symbolName = "apply1" + + let code = + $""" +let apply1 (transform: int -> int) y = transform y + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let newDoc = tryRefactor code spanStart context (new AddReturnType()) + + let expectedCode = + $""" +let apply1 (transform: int -> int) y : int = transform y + """ + + let resultText = newDoc.GetTextAsync() |> GetTaskResult + Assert.Equal(expectedCode, resultText.ToString()) + +[] +let ``Infer on member function`` () = + let symbolName = "SomeMethod" + + let code = + $""" +type SomeType(factor0: int) = + let factor = factor0 + member this.SomeMethod(a, b, c) = (a + b + c) * factor + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let newDoc = tryRefactor code spanStart context (new AddReturnType()) + + let expectedCode = + $""" +type SomeType(factor0: int) = + let factor = factor0 + member this.SomeMethod(a, b, c) : int = (a + b + c) * factor + """ + + let resultText = newDoc.GetTextAsync() |> GetTaskResult + Assert.Equal(expectedCode, resultText.ToString()) + +[] +let ``Binding another function doesnt crash`` () = + let symbolName = "getNow" + + let code = + $""" +let getNow() = + System.DateTime.Now + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let newDoc = tryRefactor code spanStart context (new AddReturnType()) + + let expectedCode = + $""" +let getNow() : System.DateTime = + System.DateTime.Now + """ + + let resultText = newDoc.GetTextAsync() |> GetTaskResult + Assert.Equal(expectedCode, resultText.ToString()) + +[] +let ``Handle already existing opens for DateTime`` () = + let symbolName = "getNow" + + let code = + $""" +open System + +let getNow() = + DateTime.Now + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let newDoc = tryRefactor code spanStart context (new AddReturnType()) + + let expectedCode = + $""" +open System + +let getNow() : DateTime = + DateTime.Now + """ + + let resultText = newDoc.GetTextAsync() |> GetTaskResult + Assert.Equal(expectedCode, resultText.ToString()) + +[] +let ``Binding linq function doesnt crash`` () = + let symbolName = "skip1" + + let code = + $""" +let skip1 elements = + System.Linq.Enumerable.Skip(elements, 1) + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let newDoc = tryRefactor code spanStart context (new AddReturnType()) + + let expectedCode = + $""" +let skip1 elements : System.Collections.Generic.IEnumerable<'a> = + System.Linq.Enumerable.Skip(elements, 1) + """ + + let resultText = newDoc.GetTextAsync() |> GetTaskResult + Assert.Equal(expectedCode, resultText.ToString()) + +[] +let ``Handle already existing opens on Linq`` () = + let symbolName = "skip1" + + let code = + $""" +open System + +let skip1 elements = + Linq.Enumerable.Skip(elements, 1) + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let newDoc = tryRefactor code spanStart context (new AddReturnType()) + + let expectedCode = + $""" +open System + +let skip1 elements : Collections.Generic.IEnumerable<'a> = + Linq.Enumerable.Skip(elements, 1) + """ + + let resultText = newDoc.GetTextAsync() |> GetTaskResult + Assert.Equal(expectedCode, resultText.ToString()) + +[] +let ``Handle already existing opens on Enumerable`` () = + let symbolName = "skip1" + + let code = + $""" +open System +open System.Linq + +let skip1 elements = + Enumerable.Skip(elements, 1) + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let newDoc = tryRefactor code spanStart context (new AddReturnType()) + + let expectedCode = + $""" +open System +open System.Linq + +let skip1 elements : Collections.Generic.IEnumerable<'a> = + Enumerable.Skip(elements, 1) + """ + + let resultText = newDoc.GetTextAsync() |> GetTaskResult + Assert.Equal(expectedCode, resultText.ToString()) + +[] +let ``Correctly infer custom type that is declared earlier in file`` () = + let symbolName = "sum" + + let code = + """ +type MyType = { Value: int } +let sum a b = {Value=a+b} + """ + + use context = TestContext.CreateWithCode code + + let spanStart = code.IndexOf symbolName + + let newDoc = tryRefactor code spanStart context (new AddReturnType()) + + let expectedCode = + """ +type MyType = { Value: int } +let sum a b : MyType = {Value=a+b} + """ + + let resultText = newDoc.GetTextAsync() |> GetTaskResult + Assert.Equal(expectedCode, resultText.ToString()) + +[] +let ``Correctly infer custom type that is declared earlier in project`` () = + let symbolName = "sum" + + let myModule = + """ +module ModuleFirst +type MyType = { Value: int } + """ + + let code = + """ +module ModuleSecond + +open ModuleFirst + +let sum a b = {Value=a+b} + """ + + let project = + { SyntheticProject.Create( + { sourceFile "First" [] with + Source = myModule + }, + { sourceFile "Second" [ "First" ] with + Source = code + } + ) with + AutoAddModules = false + } + + let solution, _ = RoslynTestHelpers.CreateSolution project + let context = new TestContext(solution) + + let spanStart = code.IndexOf symbolName + + let newDoc = tryRefactor code spanStart context (new AddReturnType()) + + let expectedCode = + """ +module ModuleSecond + +open ModuleFirst + +let sum a b : MyType = {Value=a+b} + """ + + let resultText = newDoc.GetTextAsync() |> GetTaskResult + Assert.Equal(expectedCode.Trim(' ', '\r', '\n'), resultText.ToString().Trim(' ', '\r', '\n')) diff --git a/vsintegration/tests/FSharp.Editor.Tests/Refactors/RefactorTestFramework.fs b/vsintegration/tests/FSharp.Editor.Tests/Refactors/RefactorTestFramework.fs new file mode 100644 index 00000000000..849da8c84ec --- /dev/null +++ b/vsintegration/tests/FSharp.Editor.Tests/Refactors/RefactorTestFramework.fs @@ -0,0 +1,89 @@ +module FSharp.Editor.Tests.Refactors.RefactorTestFramework + +open System +open System.Linq +open System.Collections.Generic + +open Microsoft.CodeAnalysis +open Microsoft.CodeAnalysis.Text +open Microsoft.VisualStudio.FSharp.Editor.CancellableTasks + +open FSharp.Editor.Tests.Helpers +open Microsoft.CodeAnalysis.CodeRefactorings +open Microsoft.CodeAnalysis.CodeActions +open System.Threading + +let GetTaskResult (task: Tasks.Task<'T>) = task.GetAwaiter().GetResult() + +type TestContext(Solution: Solution) = + let mutable _solution = Solution + member _.CancellationToken = CancellationToken.None + + member _.Solution + with set value = _solution <- value + and get () = _solution + + interface IDisposable with + member _.Dispose() = Solution.Workspace.Dispose() + + static member CreateWithCode(code: string) = + let solution = RoslynTestHelpers.CreateSolution(code) + new TestContext(solution) + + static member CreateWithCodeAndDependency (code: string) (codeForPreviousFile: string) = + let mutable solution = RoslynTestHelpers.CreateSolution(codeForPreviousFile) + + let firstProject = solution.Projects.First() + solution <- solution.AddDocument(DocumentId.CreateNewId(firstProject.Id), "test2.fs", code, filePath = "C:\\test2.fs") + + new TestContext(solution) + +let tryRefactor (code: string) (cursorPosition) (context: TestContext) (refactorProvider: 'T :> CodeRefactoringProvider) = + cancellableTask { + let mutable action: CodeAction = null + let existingDocument = RoslynTestHelpers.GetLastDocument context.Solution + + context.Solution <- context.Solution.WithDocumentText(existingDocument.Id, SourceText.From(code)) + + let document = RoslynTestHelpers.GetLastDocument context.Solution + + let mutable workspace = context.Solution.Workspace + + let refactoringContext = + CodeRefactoringContext(document, TextSpan(cursorPosition, 1), (fun a -> action <- a), context.CancellationToken) + + do! refactorProvider.ComputeRefactoringsAsync refactoringContext + + let! operations = action.GetOperationsAsync context.CancellationToken + + for operation in operations do + let codeChangeOperation = operation :?> ApplyChangesOperation + codeChangeOperation.Apply(workspace, context.CancellationToken) + context.Solution <- codeChangeOperation.ChangedSolution + () + + let newDocument = context.Solution.GetDocument(document.Id) + return newDocument + + } + |> CancellableTask.startWithoutCancellation + |> GetTaskResult + +let tryGetRefactoringActions (code: string) (cursorPosition) (context: TestContext) (refactorProvider: 'T :> CodeRefactoringProvider) = + cancellableTask { + let refactoringActions = new List() + let existingDocument = RoslynTestHelpers.GetLastDocument context.Solution + + context.Solution <- context.Solution.WithDocumentText(existingDocument.Id, SourceText.From(code)) + + let document = RoslynTestHelpers.GetLastDocument context.Solution + + let refactoringContext = + CodeRefactoringContext(document, TextSpan(cursorPosition, 1), (fun a -> refactoringActions.Add a), context.CancellationToken) + + do! refactorProvider.ComputeRefactoringsAsync refactoringContext + + return refactoringActions + } + |> CancellableTask.startWithoutCancellation + |> fun task -> task.Result diff --git a/vsintegration/tests/FSharp.Editor.Tests/SignatureHelpProviderTests.fs b/vsintegration/tests/FSharp.Editor.Tests/SignatureHelpProviderTests.fs index d062f26a0bd..af66c01ed69 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/SignatureHelpProviderTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/SignatureHelpProviderTests.fs @@ -16,8 +16,8 @@ open Microsoft.VisualStudio.FSharp.Editor.CancellableTasks module SignatureHelpProvider = let private DefaultDocumentationProvider = { new IDocumentationBuilder with - override doc.AppendDocumentationFromProcessedXML(_, _, _, _, _, _) = () - override doc.AppendDocumentation(_, _, _, _, _, _, _) = () + override doc.AppendDocumentationFromProcessedXML(_, _, _, _, _, _, _) = () + override doc.AppendDocumentation(_, _, _, _, _, _, _, _) = () } let checker = FSharpChecker.Create() @@ -56,7 +56,8 @@ module SignatureHelpProvider = DefaultDocumentationProvider, sourceText, caretPosition, - triggerChar + triggerChar, + EditorOptions() ) |> Async.RunSynchronously @@ -123,7 +124,8 @@ module SignatureHelpProvider = DefaultDocumentationProvider, sourceText, caretPosition, - triggerChar + triggerChar, + EditorOptions() ) |> Async.RunSynchronously @@ -155,13 +157,18 @@ module SignatureHelpProvider = |> CancellableTask.runSynchronouslyWithoutCancellation let adjustedColumnInSource = - let rec loop ch pos = - if Char.IsWhiteSpace(ch) then - loop sourceText.[pos - 1] (pos - 1) - else + let rec loop pos = + if pos = 0 then pos + else + let nextPos = pos - 1 - loop sourceText.[caretPosition - 1] (caretPosition - 1) + if not (Char.IsWhiteSpace sourceText[nextPos]) then + pos + else + loop nextPos + + loop (caretPosition - 1) let sigHelp = FSharpSignatureHelpProvider.ProvideParametersAsyncAux( @@ -175,7 +182,8 @@ module SignatureHelpProvider = sourceText, caretPosition, adjustedColumnInSource, - filePath + filePath, + EditorOptions() ) |> Async.RunSynchronously @@ -440,8 +448,8 @@ type foo5 = N1.T module ``Function argument applications`` = let private DefaultDocumentationProvider = { new IDocumentationBuilder with - override doc.AppendDocumentationFromProcessedXML(_, _, _, _, _, _) = () - override doc.AppendDocumentation(_, _, _, _, _, _, _) = () + override doc.AppendDocumentationFromProcessedXML(_, _, _, _, _, _, _) = () + override doc.AppendDocumentation(_, _, _, _, _, _, _, _) = () } [] @@ -518,7 +526,8 @@ M.f sourceText, caretPosition, adjustedColumnInSource, - filePath + filePath, + EditorOptions() ) |> Async.RunSynchronously @@ -548,6 +557,18 @@ M.f let marker = "List.map " assertSignatureHelpForFunctionApplication fileContents marker 1 0 "mapping" + [] + let ``function application in middle of pipeline with two additional arguments`` () = + let fileContents = + """ +[1..10] +|> List.fold (fun acc _ -> acc) +|> List.filter (fun x -> x > 3) + """ + + let marker = "List.fold (fun acc _ -> acc) " + assertSignatureHelpForFunctionApplication fileContents marker 2 1 "state" + [] let ``function application with function as parameter`` () = let fileContents = From 3c53e3be2bc4190b6b2435946affdbc85c0402db Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 25 Jan 2024 11:53:44 +0100 Subject: [PATCH 57/59] release notes --- docs/release-notes/.FSharp.Compiler.Service/8.0.300.md | 1 + docs/release-notes/.Language/preview.md | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md index 8fa3c363b20..0a2366d14e3 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md @@ -6,6 +6,7 @@ ### Added +* Support for nullable reference types ([PR #15181](https://github.com/dotnet/fsharp/pull/15181)) * Parser recovers on complex primary constructor patterns, better tree representation for primary constructor patterns. ([PR #16425](https://github.com/dotnet/fsharp/pull/16425)) * Name resolution: keep type vars in subsequent checks ([PR #16456](https://github.com/dotnet/fsharp/pull/16456)) * Higher-order-function-based API for working with the untyped abstract syntax tree. ([PR #16462](https://github.com/dotnet/fsharp/pull/16462)) diff --git a/docs/release-notes/.Language/preview.md b/docs/release-notes/.Language/preview.md index 0fce580b51e..33addb606b6 100644 --- a/docs/release-notes/.Language/preview.md +++ b/docs/release-notes/.Language/preview.md @@ -1,5 +1,6 @@ ### Added +* Support for nullable reference types ([PR #15181](https://github.com/dotnet/fsharp/pull/15181)) * Better generic unmanaged structs handling. ([Language suggestion #692](https://github.com/fsharp/fslang-suggestions/issues/692), [PR #12154](https://github.com/dotnet/fsharp/pull/12154)) * Bidirectional F#/C# interop for 'unmanaged' constraint. ([PR #12154](https://github.com/dotnet/fsharp/pull/12154)) * Make `.Is*` discriminated union properties visible. ([Language suggestion #222](https://github.com/fsharp/fslang-suggestions/issues/222), [PR #16341](https://github.com/dotnet/fsharp/pull/16341)) From 3250b7e681431d4f66d43fa2d3ba3c8bd460b5cd Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 25 Jan 2024 14:46:20 +0100 Subject: [PATCH 58/59] Fix ILType.Array import (#16585) --- src/Compiler/Checking/import.fs | 4 +- .../FSharpChecker/TransparentCompiler.fs | 6 +-- .../Language/NullableCsharpImportTests.fs | 53 ++++++++++++++++--- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/src/Compiler/Checking/import.fs b/src/Compiler/Checking/import.fs index f629df6c5e9..cf85e3c2e56 100644 --- a/src/Compiler/Checking/import.fs +++ b/src/Compiler/Checking/import.fs @@ -316,10 +316,10 @@ let rec ImportILTypeWithNullness (env: ImportMap) m tinst (nf:Nullness.NullableF | ILType.Void -> env.g.unit_ty,nf - | ILType.Array(bounds, ty) -> + | ILType.Array(bounds, innerTy) -> let n = bounds.Rank let (arrayNullness,nf) = Nullness.evaluateFirstOrderNullnessAndAdvance ty nf - let struct(elemTy,nf) = ImportILTypeWithNullness env m tinst nf ty + let struct(elemTy,nf) = ImportILTypeWithNullness env m tinst nf innerTy mkArrayTy env.g n arrayNullness elemTy m, nf | ILType.Boxed tspec | ILType.Value tspec -> diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs index 57a9e266fe8..60c7e8be881 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs @@ -237,8 +237,8 @@ let ``File is not checked twice`` () = |> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList) |> Map - Assert.Equal([Weakened; Started; Finished], intermediateTypeChecks["FileFirst.fs"]) - Assert.Equal([Weakened; Started; Finished], intermediateTypeChecks["FileThird.fs"]) + Assert.Equal([Weakened; Requested; Started; Finished], intermediateTypeChecks["FileFirst.fs"]) + Assert.Equal([Weakened; Requested; Started; Finished], intermediateTypeChecks["FileThird.fs"]) [] let ``If a file is checked as a dependency it's not re-checked later`` () = @@ -261,7 +261,7 @@ let ``If a file is checked as a dependency it's not re-checked later`` () = |> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList) |> Map - Assert.Equal([Weakened; Started; Finished], intermediateTypeChecks["FileThird.fs"]) + Assert.Equal([Weakened; Requested; Started; Finished; Requested], intermediateTypeChecks["FileThird.fs"]) // [] TODO: differentiate complete and minimal checking requests diff --git a/tests/FSharp.Compiler.ComponentTests/Language/NullableCsharpImportTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/NullableCsharpImportTests.fs index 60930ad56dd..f3c9577530a 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/NullableCsharpImportTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/NullableCsharpImportTests.fs @@ -1,9 +1,54 @@ module Language.NullableCSharpImport -open FSharp.Test open Xunit +open FSharp.Test open FSharp.Test.Compiler +let typeCheckWithStrictNullness cu = + cu + |> withLangVersionPreview + |> withCheckNulls + |> withWarnOn 3261 + |> withOptions ["--warnaserror+"] + |> compile + +[] +let ``Passing null to IlGenerator BeginCatchBlock is fine`` () = + FSharp """module MyLibrary +open System.Reflection.Emit +open System + +let passValueToIt (ilg: ILGenerator) = + let maybeType : Type | null = null + ilg.BeginCatchBlock(maybeType)""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed + +[] +let ``Consumption of netstandard2 BCL api which is not annotated`` () = + FSharp """module MyLibrary +open System.Reflection + +[] +type PublicKey = + | PublicKey of byte[] + | PublicKeyToken of byte[] + +let FromAssemblyName (aname: AssemblyName) = + match aname.GetPublicKey() with + | Null + | NonNull [||] -> + match aname.GetPublicKeyToken() with + | Null + | NonNull [||] -> None + | NonNull bytes -> Some(PublicKeyToken bytes) + | NonNull bytes -> Some(PublicKey bytes)""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed + + [] let ``Consumption of nullable C# - no generics, just strings in methods and fields`` () = let csharpLib = @@ -67,12 +112,8 @@ let ``Consumption of nullable C# - no generics, just strings in methods and fiel """ |> asLibrary - |> withLangVersionPreview |> withReferences [csharpLib] - |> withCheckNulls - |> withWarnOn 3261 - |> withOptions ["--warnaserror+"] - |> compile + |> typeCheckWithStrictNullness |> shouldFail |> withDiagnostics [ Error 3261, Line 5, Col 40, Line 5, Col 85, "Nullness warning: The types 'string' and 'string | null' do not have compatible nullability." From e0f1634014503fafa0124e112f90f78172f0457b Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 30 Jan 2024 11:09:44 +0100 Subject: [PATCH 59/59] Nullness - reading+writing metadata for 'inherits' and interface implementations (#16597) --- Directory.Build.props | 6 +- azure-pipelines.yml | 27 +- .../.FSharp.Compiler.Service/8.0.300.md | 5 +- eng/Build.ps1 | 18 ++ eng/Version.Details.xml | 4 +- global.json | 2 +- src/Compiler/AbstractIL/il.fs | 11 +- src/Compiler/AbstractIL/il.fsi | 6 +- src/Compiler/AbstractIL/ilread.fs | 21 +- src/Compiler/AbstractIL/ilwrite.fs | 16 +- src/Compiler/Checking/TypeHierarchy.fs | 21 +- src/Compiler/CodeGen/EraseClosures.fs | 2 + src/Compiler/CodeGen/EraseUnions.fs | 1 + src/Compiler/CodeGen/IlxGen.fs | 46 ++- .../GraphChecking/FileContentMapping.fs | 7 +- .../Driver/GraphChecking/GraphProcessing.fs | 10 +- src/Compiler/Service/SynExpr.fs | 10 +- .../EmittedIL/Nullness/NullableInheritance.fs | 24 ++ .../NullableInheritance.fs.il.net472.bsl | 275 ++++++++++++++++++ .../NullableInheritance.fs.il.netcore.bsl | 209 +++++++++++++ .../EmittedIL/Nullness/NullnessMetadata.fs | 5 + .../Graph/FileContentMappingTests.fs | 43 ++- ...ervice.SurfaceArea.netstandard20.debug.bsl | 22 +- ...vice.SurfaceArea.netstandard20.release.bsl | 22 +- .../HistoricalBenchmark.Runner.fsproj | 1 + .../BackgroundCompilerBenchmarks.fs | 2 +- tests/scripts/update-baselines.fsx | 4 +- .../service/ModuleReaderCancellationTests.fs | 2 +- .../LanguageService/WorkspaceExtensions.fs | 2 +- .../RemoveUnnecessaryParenthesesTests.fs | 18 ++ 30 files changed, 755 insertions(+), 87 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullableInheritance.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullableInheritance.fs.il.net472.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullableInheritance.fs.il.netcore.bsl diff --git a/Directory.Build.props b/Directory.Build.props index 10c53909035..a1b18784e91 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -16,10 +16,6 @@ true - - true - - true @@ -28,6 +24,8 @@ + true + true false true true diff --git a/azure-pipelines.yml b/azure-pipelines.yml index afd393f8200..df00f0bc2c2 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,4 +1,4 @@ -# CI and PR triggers +# CI and PR triggers trigger: branches: include: @@ -110,13 +110,10 @@ stages: demands: ImageOverride -equals windows.vs2022preview.amd64 timeoutInMinutes: 300 variables: - - group: DotNet-Blob-Feed - group: DotNet-Symbol-Server-Pats - group: DotNet-DevDiv-Insertion-Workflow-Variables - name: _SignType value: Real - - name: _DotNetPublishToBlobFeed - value: true steps: - checkout: self clean: true @@ -131,9 +128,6 @@ stages: /p:MicroBuild_SigningEnabled=true /p:OverridePackageSource=https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json /p:TeamName=$(_TeamName) - /p:DotNetPublishBlobFeedKey=$(dotnetfeed-storage-access-key-1) - /p:DotNetPublishBlobFeedUrl=https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json - /p:DotNetPublishToBlobFeed=true /p:DotNetPublishUsingPipelines=$(_PublishUsingPipelines) /p:DotNetArtifactsCategory=$(_DotNetArtifactsCategory) /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) @@ -724,25 +718,10 @@ stages: steps: - checkout: self clean: true - - script: dotnet --list-sdks - displayName: Report dotnet SDK versions - - task: UseDotNet@2 - displayName: install SDK - inputs: - packageType: sdk - useGlobalJson: true - includePreviewVersions: true - workingDirectory: $(Build.SourcesDirectory) - installationPath: $(Agent.ToolsDirectory)/dotnet - - script: dotnet build -c $(_BuildConfig) .\FSharp.Benchmarks.sln /bl:\"artifacts/log/$(_BuildConfig)/BenchmarkBuild.binlog\" - workingDirectory: $(Build.SourcesDirectory) - displayName: Plain build of FSharp.Benchmarks.sln + - script: eng\CIBuild.cmd -configuration $(_BuildConfig) -testBenchmarks + displayName: Smoke test fast benchmarks continueOnError: true condition: always() - - script: .\Build.cmd -c $(_BuildConfig) - - pwsh: ./SmokeTestBenchmarks.ps1 - workingDirectory: $(Build.SourcesDirectory)/tests/benchmarks - displayName: Smoke test fast benchmarks # Test trimming on Windows - job: Build_And_Test_Trimming_Windows diff --git a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md index 54ce6d6be5d..ee3affe24f9 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md @@ -2,13 +2,14 @@ * Code generated files with > 64K methods and generated symbols crash when loaded. Use infered sequence points for debugging. ([Issue #16399](https://github.com/dotnet/fsharp/issues/16399), [#PR 16514](https://github.com/dotnet/fsharp/pull/16514)) * `nameof Module` expressions and patterns are processed to link files in `--test:GraphBasedChecking`. ([PR #16550](https://github.com/dotnet/fsharp/pull/16550)) -* Graph Based Checking doesn't throw on invalid parsed input so it can be used for IDE scenarios ([PR #16575](https://github.com/dotnet/fsharp/pull/16575)) +* Graph Based Checking doesn't throw on invalid parsed input so it can be used for IDE scenarios ([PR #16575](https://github.com/dotnet/fsharp/pull/16575), [PR #16588](https://github.com/dotnet/fsharp/pull/16588)) +* Keep parens for problematic exprs (`if`, `match`, etc.) in `$"{(…):N0}"`, `$"{(…),-3}"`, etc. ([PR #16578](https://github.com/dotnet/fsharp/pull/16578)) ### Added * Support for nullable reference types ([PR #15181](https://github.com/dotnet/fsharp/pull/15181)) -* The stackguard depth for ILPdbWriter.unshadowScopes can be modified via the environment variable `FSHARP_ILPdb_UnshadowScopes_StackGuardDepth`([PR #16583](https://github.com/dotnet/fsharp/pull/16583)) +* The stackguard depth for ILPdbWriter.unshadowScopes can be modified via the environment variable `FSHARP_ILPdb_UnshadowScopes_StackGuardDepth`([PR #16583](https://github.com/dotnet/fsharp/pull/16583)) * Parser recovers on complex primary constructor patterns, better tree representation for primary constructor patterns. ([PR #16425](https://github.com/dotnet/fsharp/pull/16425)) * Name resolution: keep type vars in subsequent checks ([PR #16456](https://github.com/dotnet/fsharp/pull/16456)) * Higher-order-function-based API for working with the untyped abstract syntax tree. ([PR #16462](https://github.com/dotnet/fsharp/pull/16462)) diff --git a/eng/Build.ps1 b/eng/Build.ps1 index b713a86effa..fe7eb56a5b1 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -62,6 +62,7 @@ param ( [switch]$testAllButIntegration, [switch]$testpack, [switch]$testAOT, + [switch]$testBenchmarks, [string]$officialSkipTests = "false", [switch]$noVisualStudio, [switch]$sourceBuild, @@ -111,6 +112,7 @@ function Print-Usage() { Write-Host " -testVs Run F# editor unit tests" Write-Host " -testpack Verify built packages" Write-Host " -testAOT Run AOT/Trimming tests" + Write-Host " -testBenchmarks Build and Run Benchmark suite" Write-Host " -officialSkipTests Set to 'true' to skip running tests" Write-Host "" Write-Host "Advanced settings:" @@ -176,6 +178,7 @@ function Process-Arguments() { $script:testVs = $False $script:testpack = $False $script:testAOT = $False + $script:testBenchmarks = $False $script:verifypackageshipstatus = $True } @@ -211,6 +214,10 @@ function Process-Arguments() { $script:pack = $True; } + if ($testBenchmarks) { + $script:testBenchmarks = $True + } + foreach ($property in $properties) { if (!$property.StartsWith("/p:", "InvariantCultureIgnoreCase")) { Write-Host "Invalid argument: $property" @@ -541,12 +548,17 @@ try { } } + if ($testBenchmarks) { + BuildSolution "FSharp.Benchmarks.sln" $False + } + if ($pack) { $properties_storage = $properties $properties += "/p:GenerateSbom=false" BuildSolution "Microsoft.FSharp.Compiler.sln" $True $properties = $properties_storage } + if ($build) { VerifyAssemblyVersionsAndSymbols } @@ -662,6 +674,12 @@ try { Pop-Location } + if ($testBenchmarks) { + Push-Location "$RepoRoot\tests\benchmarks" + ./SmokeTestBenchmarks.ps1 + Pop-Location + } + # verify nupkgs have access to the source code $nupkgtestFailed = $false if ($testpack) { diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 732b37657ea..4be35244cae 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -29,9 +29,9 @@ - + https://github.com/dotnet/arcade - 4c941e2e3ae61502bd4ffd711930f662fd808375 + 07cf24f27ee58b5d1a9662334a101d84bd1e07e5 diff --git a/global.json b/global.json index 56134e06fd6..60ffcefc016 100644 --- a/global.json +++ b/global.json @@ -17,7 +17,7 @@ "perl": "5.38.0.1" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24073.2", + "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24075.5", "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23255.2" } } diff --git a/src/Compiler/AbstractIL/il.fs b/src/Compiler/AbstractIL/il.fs index 3b7df226c9f..4859f510c01 100644 --- a/src/Compiler/AbstractIL/il.fs +++ b/src/Compiler/AbstractIL/il.fs @@ -2612,6 +2612,7 @@ type ILTypeDef attributes: TypeAttributes, layout: ILTypeDefLayout, implements: ILTypes, + implementsCustomAttrs: (ILAttributesStored * int) list option, genericParams: ILGenericParameterDefs, extends: ILType option, methods: ILMethodDefs, @@ -2632,6 +2633,7 @@ type ILTypeDef attributes, layout, implements, + implementsCustomAttrs, genericParams, extends, methods, @@ -2648,6 +2650,7 @@ type ILTypeDef attributes, layout, implements, + implementsCustomAttrs, genericParams, extends, methods, @@ -2674,6 +2677,8 @@ type ILTypeDef member _.Implements = implements + member _.ImplementsCustomAttrs = implementsCustomAttrs + member _.Extends = extends member _.Methods = methods @@ -2710,7 +2715,8 @@ type ILTypeDef ?properties, ?isKnownToBeAttribute, ?customAttrs, - ?securityDecls + ?securityDecls, + ?implementsCustomAttrs ) = ILTypeDef( name = defaultArg name x.Name, @@ -2719,6 +2725,7 @@ type ILTypeDef genericParams = defaultArg genericParams x.GenericParams, nestedTypes = defaultArg nestedTypes x.NestedTypes, implements = defaultArg implements x.Implements, + implementsCustomAttrs = defaultArg implementsCustomAttrs x.ImplementsCustomAttrs, extends = defaultArg extends x.Extends, methods = defaultArg methods x.Methods, securityDecls = defaultArg securityDecls x.SecurityDecls, @@ -4192,6 +4199,7 @@ let mkILGenericClass (nm, access, genparams, extends, impl, methods, fields, nes attributes = attributes, genericParams = genparams, implements = impl, + implementsCustomAttrs = None, layout = ILTypeDefLayout.Auto, extends = Some extends, methods = methods, @@ -4216,6 +4224,7 @@ let mkRawDataValueTypeDef (iltyp_ValueType: ILType) (nm, size, pack) = ||| TypeAttributes.BeforeFieldInit ||| TypeAttributes.AnsiClass), implements = [], + implementsCustomAttrs = None, extends = Some iltyp_ValueType, layout = ILTypeDefLayout.Explicit { Size = Some size; Pack = Some pack }, methods = emptyILMethods, diff --git a/src/Compiler/AbstractIL/il.fsi b/src/Compiler/AbstractIL/il.fsi index 8ae223081ac..bb503932b86 100644 --- a/src/Compiler/AbstractIL/il.fsi +++ b/src/Compiler/AbstractIL/il.fsi @@ -1507,6 +1507,7 @@ type ILTypeDef = attributes: TypeAttributes * layout: ILTypeDefLayout * implements: ILTypes * + implementsCustomAttrs: (ILAttributesStored * int) list option * genericParams: ILGenericParameterDefs * extends: ILType option * methods: ILMethodDefs * @@ -1527,6 +1528,7 @@ type ILTypeDef = attributes: TypeAttributes * layout: ILTypeDefLayout * implements: ILTypes * + implementsCustomAttrs: (ILAttributesStored * int) list option * genericParams: ILGenericParameterDefs * extends: ILType option * methods: ILMethodDefs * @@ -1546,6 +1548,7 @@ type ILTypeDef = member Layout: ILTypeDefLayout member NestedTypes: ILTypeDefs member Implements: ILTypes + member ImplementsCustomAttrs: (ILAttributesStored * int) list option member Extends: ILType option member Methods: ILMethodDefs member SecurityDecls: ILSecurityDecls @@ -1604,7 +1607,8 @@ type ILTypeDef = ?properties: ILPropertyDefs * ?isKnownToBeAttribute: bool * ?customAttrs: ILAttributes * - ?securityDecls: ILSecurityDecls -> + ?securityDecls: ILSecurityDecls * + ?implementsCustomAttrs: (ILAttributesStored * int) list option -> ILTypeDef /// Represents a prefix of information for ILTypeDef. diff --git a/src/Compiler/AbstractIL/ilread.fs b/src/Compiler/AbstractIL/ilread.fs index 6dcc4ee33c6..08c82f9b270 100644 --- a/src/Compiler/AbstractIL/ilread.fs +++ b/src/Compiler/AbstractIL/ilread.fs @@ -1180,6 +1180,7 @@ type ILMetadataReader = customAttrsReader_Module: ILAttributesStored customAttrsReader_Assembly: ILAttributesStored customAttrsReader_TypeDef: ILAttributesStored + customAttrsReader_InterfaceImpl: ILAttributesStored customAttrsReader_GenericParam: ILAttributesStored customAttrsReader_FieldDef: ILAttributesStored customAttrsReader_MethodDef: ILAttributesStored @@ -1450,11 +1451,16 @@ let seekReadParamRow (ctxt: ILMetadataReader) mdv idx = (flags, seq, nameIdx) /// Read Table InterfaceImpl. -let seekReadInterfaceImplRow (ctxt: ILMetadataReader) mdv idx = +let private seekReadInterfaceImplRow (ctxt: ILMetadataReader) mdv idx = let mutable addr = ctxt.rowAddr TableNames.InterfaceImpl idx let tidx = seekReadUntaggedIdx TableNames.TypeDef ctxt mdv &addr let intfIdx = seekReadTypeDefOrRefOrSpecIdx ctxt mdv &addr - (tidx, intfIdx) + + struct {| + TypeIdx = tidx + IntfIdx = intfIdx + IntImplIdx = idx + |} /// Read Table MemberRef. let seekReadMemberRefRow (ctxt: ILMetadataReader) mdv idx = @@ -2144,7 +2150,10 @@ and typeDefReader ctxtH : ILTypeDefStored = let mdefs = seekReadMethods ctxt numTypars methodsIdx endMethodsIdx let fdefs = seekReadFields ctxt (numTypars, hasLayout) fieldsIdx endFieldsIdx let nested = seekReadNestedTypeDefs ctxt idx - let impls = seekReadInterfaceImpls ctxt mdv numTypars idx + + let impls, intImplsAttrs = + seekReadInterfaceImpls ctxt mdv numTypars idx |> List.unzip + let mimpls = seekReadMethodImpls ctxt numTypars idx let props = seekReadProperties ctxt numTypars idx let events = seekReadEvents ctxt numTypars idx @@ -2156,6 +2165,7 @@ and typeDefReader ctxtH : ILTypeDefStored = layout = layout, nestedTypes = nested, implements = impls, + implementsCustomAttrs = Some intImplsAttrs, extends = super, methods = mdefs, securityDeclsStored = ctxt.securityDeclsReader_TypeDef, @@ -2192,10 +2202,10 @@ and seekReadInterfaceImpls (ctxt: ILMetadataReader) mdv numTypars tidx = seekReadIndexedRows ( ctxt.getNumRows TableNames.InterfaceImpl, seekReadInterfaceImplRow ctxt mdv, - fst, + (fun x -> x.TypeIdx), simpleIndexCompare tidx, isSorted ctxt TableNames.InterfaceImpl, - (snd >> seekReadTypeDefOrRef ctxt numTypars AsObject []) + (fun x -> (seekReadTypeDefOrRef ctxt numTypars AsObject [] x.IntfIdx), (ctxt.customAttrsReader_InterfaceImpl, x.IntImplIdx)) ) and seekReadGenericParams ctxt numTypars (a, b) : ILGenericParameterDefs = @@ -4487,6 +4497,7 @@ let openMetadataReader customAttrsReader_Module = customAttrsReader ctxtH hca_Module customAttrsReader_Assembly = customAttrsReader ctxtH hca_Assembly customAttrsReader_TypeDef = customAttrsReader ctxtH hca_TypeDef + customAttrsReader_InterfaceImpl = customAttrsReader ctxtH hca_InterfaceImpl customAttrsReader_GenericParam = customAttrsReader ctxtH hca_GenericParam customAttrsReader_FieldDef = customAttrsReader ctxtH hca_FieldDef customAttrsReader_MethodDef = customAttrsReader ctxtH hca_MethodDef diff --git a/src/Compiler/AbstractIL/ilwrite.fs b/src/Compiler/AbstractIL/ilwrite.fs index f41c8aaa08d..c4c43f6a5fc 100644 --- a/src/Compiler/AbstractIL/ilwrite.fs +++ b/src/Compiler/AbstractIL/ilwrite.fs @@ -554,6 +554,8 @@ type cenv = methodDefIdxs: Dictionary + implementsIdxs: Dictionary + propertyDefs: MetadataTable eventDefs: MetadataTable @@ -1281,7 +1283,7 @@ and GetTypeAsImplementsRow cenv env tidx ty = TypeDefOrRefOrSpec (tdorTag, tdorRow) |] and GenImplementsPass2 cenv env tidx ty = - AddUnsharedRow cenv TableNames.InterfaceImpl (GetTypeAsImplementsRow cenv env tidx ty) |> ignore + AddUnsharedRow cenv TableNames.InterfaceImpl (GetTypeAsImplementsRow cenv env tidx ty) and GetKeyForEvent tidx (x: ILEventDef) = EventKey (tidx, x.Name) @@ -1317,7 +1319,8 @@ and GenTypeDefPass2 pidx enc cenv (tdef: ILTypeDef) = // Now generate or assign index numbers for tables referenced by the maps. // Don't yet generate contents of these tables - leave that to pass3, as // code may need to embed these entries. - tdef.Implements |> List.iter (GenImplementsPass2 cenv env tidx) + cenv.implementsIdxs[tidx] <- tdef.Implements |> List.map (GenImplementsPass2 cenv env tidx) + tdef.Fields.AsList() |> List.iter (GenFieldDefPass2 tdef cenv tidx) tdef.Methods |> Seq.iter (GenMethodDefPass2 tdef cenv tidx) // Generation of property & event definitions for **ref assemblies** is checking existence of generated method definitions. @@ -2866,6 +2869,14 @@ let rec GenTypeDefPass3 enc cenv (tdef: ILTypeDef) = try let env = envForTypeDef tdef let tidx = GetIdxForTypeDef cenv (TdKey(enc, tdef.Name)) + + match tdef.ImplementsCustomAttrs with + | None -> () + | Some attrList -> + attrList + |> List.zip cenv.implementsIdxs[tidx] + |> List.iter (fun (impIdx,(attrs,metadataIdx)) -> GenCustomAttrsPass3Or4 cenv (hca_InterfaceImpl,impIdx) (attrs.GetCustomAttrs metadataIdx)) + tdef.Properties.AsList() |> List.iter (GenPropertyPass3 cenv env) tdef.Events.AsList() |> List.iter (GenEventPass3 cenv env) tdef.Fields.AsList() |> List.iter (GenFieldDefPass3 tdef cenv env) @@ -3130,6 +3141,7 @@ let generateIL ( methodDefIdxsByKey = MetadataTable<_>.New("method defs", EqualityComparer.Default) // This uses reference identity on ILMethodDef objects methodDefIdxs = Dictionary<_, _>(100, HashIdentity.Reference) + implementsIdxs = Dictionary<_, _>(100, HashIdentity.Structural) propertyDefs = MetadataTable<_>.New("property defs", EqualityComparer.Default) eventDefs = MetadataTable<_>.New("event defs", EqualityComparer.Default) typeDefs = MetadataTable<_>.New("type defs", EqualityComparer.Default) diff --git a/src/Compiler/Checking/TypeHierarchy.fs b/src/Compiler/Checking/TypeHierarchy.fs index a629857245a..69c1924f3d7 100644 --- a/src/Compiler/Checking/TypeHierarchy.fs +++ b/src/Compiler/Checking/TypeHierarchy.fs @@ -9,6 +9,7 @@ open FSharp.Compiler open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.DiagnosticsLogger open FSharp.Compiler.Import +open FSharp.Compiler.Import.Nullness open FSharp.Compiler.Features open FSharp.Compiler.Syntax open FSharp.Compiler.SyntaxTreeOps @@ -56,7 +57,10 @@ let GetSuperTypeOfType g amap m ty = match tdef.Extends with | None -> None // 'inherit' cannot refer to a nullable type - | Some ilTy -> Some (RescopeAndImportILTypeSkipNullness scoref amap m tinst ilTy) + | Some ilTy -> + let typeAttrs = AttributesFromIL(tdef.MetadataIndex,tdef.CustomAttrsStored) + let nullness = {DirectAttributes = typeAttrs; Fallback = FromClass typeAttrs} + Some (RescopeAndImportILType scoref amap m tinst nullness ilTy) | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> if isFSharpObjModelTy g ty || isFSharpExceptionTy g ty then @@ -114,10 +118,17 @@ let GetImmediateInterfacesOfMetadataType g amap m skipUnref ty (tcref: TyconRef) // succeeded with more reported. There are pathological corner cases where this // doesn't apply: e.g. for mscorlib interfaces like IComparable, but we can always // assume those are present. - for intfTy in tdef.Implements do - if skipUnref = SkipUnrefInterfaces.No || CanRescopeAndImportILType scoref amap m intfTy then - // Implementing an interface cannot refer to a nullable type - RescopeAndImportILTypeSkipNullness scoref amap m tinst intfTy + match tdef.ImplementsCustomAttrs with + | Some attrsList when g.langFeatureNullness && g.checkNullness -> + for (attrs,attrsIdx),intfTy in tdef.Implements |> List.zip attrsList do + if skipUnref = SkipUnrefInterfaces.No || CanRescopeAndImportILType scoref amap m intfTy then + let typeAttrs = AttributesFromIL(attrsIdx,attrs) + let nullness = {DirectAttributes = typeAttrs; Fallback = FromClass typeAttrs} + RescopeAndImportILType scoref amap m tinst nullness intfTy + | _ -> + for intfTy in tdef.Implements do + if skipUnref = SkipUnrefInterfaces.No || CanRescopeAndImportILType scoref amap m intfTy then + RescopeAndImportILTypeSkipNullness scoref amap m tinst intfTy | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> for intfTy in tcref.ImmediateInterfaceTypesOfFSharpTycon do instType (mkInstForAppTy g ty) intfTy ] diff --git a/src/Compiler/CodeGen/EraseClosures.fs b/src/Compiler/CodeGen/EraseClosures.fs index cf1499f0c30..7e5d0df8810 100644 --- a/src/Compiler/CodeGen/EraseClosures.fs +++ b/src/Compiler/CodeGen/EraseClosures.fs @@ -573,6 +573,7 @@ let rec convIlxClosureDef cenv encl (td: ILTypeDef) clo = genericParams = td.GenericParams, attributes = td.Attributes, implements = [], + implementsCustomAttrs = None, nestedTypes = emptyILTypeDefs, layout = ILTypeDefLayout.Auto, extends = Some cenv.mkILTyFuncTy, @@ -707,6 +708,7 @@ let rec convIlxClosureDef cenv encl (td: ILTypeDef) clo = genericParams = td.GenericParams, attributes = td.Attributes, implements = [], + implementsCustomAttrs = None, layout = ILTypeDefLayout.Auto, nestedTypes = emptyILTypeDefs, extends = Some nowEnvParentClass, diff --git a/src/Compiler/CodeGen/EraseUnions.fs b/src/Compiler/CodeGen/EraseUnions.fs index c500f8ae511..508855f67a8 100644 --- a/src/Compiler/CodeGen/EraseUnions.fs +++ b/src/Compiler/CodeGen/EraseUnions.fs @@ -1565,6 +1565,7 @@ let mkClassUnionDef attributes = enum 0, layout = ILTypeDefLayout.Auto, implements = [], + implementsCustomAttrs = None, extends = Some g.ilg.typ_Object, methods = emptyILMethods, securityDecls = emptyILSecurityDecls, diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 66245cfe58f..569457f27fe 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -6186,6 +6186,7 @@ and GenStructStateMachine cenv cgbuf eenvouter (res: LoweredStateMachine) sequel methodImpls = mkILMethodImpls mimpls, nestedTypes = emptyILTypeDefs, implements = ilInterfaceTys, + implementsCustomAttrs = None, extends = Some super, isKnownToBeAttribute = false, securityDecls = emptyILSecurityDecls @@ -6614,6 +6615,7 @@ and GenClosureTypeDefs methodImpls = mkILMethodImpls mimpls, nestedTypes = emptyILTypeDefs, implements = ilIntfTys, + implementsCustomAttrs = None, extends = Some ext, isKnownToBeAttribute = false, securityDecls = emptyILSecurityDecls @@ -10569,6 +10571,19 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) = tycon.ImmediateInterfaceTypesOfFSharpTycon |> List.map (GenType cenv m eenvinner.tyenv) + let ilIntCustomAttrs = + if g.langFeatureNullness && g.checkNullness && not (isNil ilIntfTys) then + tycon.ImmediateInterfaceTypesOfFSharpTycon + |> List.map ( + GenAdditionalAttributesForTy g + >> mkILCustomAttrs + >> ILAttributesStored.Given + >> (fun x -> x, 0) + ) + |> Some + else + None + let ilTypeName = tref.Name let hidden = IsHiddenTycon eenv.sigToImplRemapInfo tycon @@ -11171,16 +11186,20 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) = let ilAttrs = ilCustomAttrs @ [ - mkCompilationMappingAttr - g - (int ( - if isObjectType then - SourceConstructFlags.ObjectType - elif hiddenRepr then - SourceConstructFlags.RecordType ||| SourceConstructFlags.NonPublicRepresentation - else - SourceConstructFlags.RecordType - )) + yield + mkCompilationMappingAttr + g + (int ( + if isObjectType then + SourceConstructFlags.ObjectType + elif hiddenRepr then + SourceConstructFlags.RecordType ||| SourceConstructFlags.NonPublicRepresentation + else + SourceConstructFlags.RecordType + )) + + if not (ilBaseTy.GenericArgs.IsEmpty) then + yield! GenAdditionalAttributesForTy g super ] let isKnownToBeAttribute = @@ -11211,7 +11230,11 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) = .WithSerializable(isSerializable) .WithAbstract(isAbstract) .WithImport(isComInteropTy g thisTy) - .With(methodImpls = mkILMethodImpls methodImpls, isKnownToBeAttribute = isKnownToBeAttribute) + .With( + methodImpls = mkILMethodImpls methodImpls, + isKnownToBeAttribute = isKnownToBeAttribute, + implementsCustomAttrs = ilIntCustomAttrs + ) let tdLayout, tdEncoding = match TryFindFSharpAttribute g g.attrib_StructLayoutAttribute tycon.Attribs with @@ -11374,6 +11397,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) = methodImpls = mkILMethodImpls methodImpls, nestedTypes = emptyILTypeDefs, implements = ilIntfTys, + implementsCustomAttrs = None, extends = Some( if tycon.IsStructOrEnumTycon then diff --git a/src/Compiler/Driver/GraphChecking/FileContentMapping.fs b/src/Compiler/Driver/GraphChecking/FileContentMapping.fs index 683460a2238..020ff817375 100644 --- a/src/Compiler/Driver/GraphChecking/FileContentMapping.fs +++ b/src/Compiler/Driver/GraphChecking/FileContentMapping.fs @@ -9,10 +9,9 @@ type Continuations = ((FileContentEntry list -> FileContentEntry list) -> FileCo let collectFromOption (mapping: 'T -> 'U list) (t: 'T option) : 'U list = List.collect mapping (Option.toList t) let longIdentToPath (skipLast: bool) (longId: LongIdent) : LongIdentifier = - if skipLast then - List.take (longId.Length - 1) longId - else - longId + match skipLast, longId with + | true, _ :: _ -> List.take (longId.Length - 1) longId + | _ -> longId |> List.map (fun ident -> ident.idText) let synLongIdentToPath (skipLast: bool) (synLongIdent: SynLongIdent) = diff --git a/src/Compiler/Driver/GraphChecking/GraphProcessing.fs b/src/Compiler/Driver/GraphChecking/GraphProcessing.fs index afe491b4b74..37ecc35041d 100644 --- a/src/Compiler/Driver/GraphChecking/GraphProcessing.fs +++ b/src/Compiler/Driver/GraphChecking/GraphProcessing.fs @@ -230,8 +230,12 @@ let processGraphAsync<'Item, 'Result when 'Item: equality and 'Item: comparison> let processedCount = IncrementableInt(0) - let raiseExn (item, ex: exn) = - localCts.Cancel() + let handleExn (item, ex: exn) = + try + localCts.Cancel() + with :? ObjectDisposedException -> + // If it's disposed already, it means that the processing has already finished, most likely due to cancellation or failure in another node. + () match ex with | :? OperationCanceledException -> completionSignal.TrySetCanceled() @@ -252,7 +256,7 @@ let processGraphAsync<'Item, 'Result when 'Item: equality and 'Item: comparison> match res with | Choice1Of2() -> () - | Choice2Of2 ex -> raiseExn (node.Info.Item, ex) + | Choice2Of2 ex -> handleExn (node.Info.Item, ex) }, cts.Token ) diff --git a/src/Compiler/Service/SynExpr.fs b/src/Compiler/Service/SynExpr.fs index 0df9a1a1c17..41dbd4d4d18 100644 --- a/src/Compiler/Service/SynExpr.fs +++ b/src/Compiler/Service/SynExpr.fs @@ -423,7 +423,9 @@ module SynExpr = | SynExpr.MatchLambda(matchClauses = Last(SynMatchClause(resultExpr = expr))) | SynExpr.MatchBang(clauses = Last(SynMatchClause(resultExpr = expr))) | SynExpr.TryWith(withCases = Last(SynMatchClause(resultExpr = expr))) - | SynExpr.TryFinally(finallyExpr = expr) -> loop expr + | SynExpr.TryFinally(finallyExpr = expr) + | SynExpr.Do(expr = expr) + | SynExpr.DoBang(expr = expr) -> loop expr | _ -> ValueNone loop @@ -810,6 +812,12 @@ module SynExpr = -> true + | SynExpr.InterpolatedString(contents = contents), (SynExpr.Tuple(isStruct = false) | Dangling.Problematic _) -> + contents + |> List.exists (function + | SynInterpolatedStringPart.FillExpr(qualifiers = Some _) -> true + | _ -> false) + | SynExpr.Record(copyInfo = Some(SynExpr.Paren(expr = Is inner), _)), Dangling.Problematic _ | SynExpr.AnonRecd(copyInfo = Some(SynExpr.Paren(expr = Is inner), _)), Dangling.Problematic _ -> true diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullableInheritance.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullableInheritance.fs new file mode 100644 index 00000000000..19fd926e2fe --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullableInheritance.fs @@ -0,0 +1,24 @@ +module MyTestModule + +open System +open System.Collections.Generic + + +type DerivedWhichAllowsNull() = + inherit ResizeArray() + member x.FirstItem = x[0] + +type DerivedWithoutNull() = + inherit ResizeArray() + member x.FirstItem = x[0] + +type ICanGetAnything<'T> = + abstract member Get : unit -> 'T + +type MyClassImplementingTheSameInterface() = + interface ICanGetAnything with + member x.Get() = null + interface ICanGetAnything>> with + member x.Get() = new ResizeArray<_>() + interface ICanGetAnything | null> with + member x.Get() = null \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullableInheritance.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullableInheritance.fs.il.net472.bsl new file mode 100644 index 00000000000..fbb63d7ff9e --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullableInheritance.fs.il.net472.bsl @@ -0,0 +1,275 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.dll + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed MyTestModule + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public DerivedWhichAllowsNull + extends class [runtime]System.Collections.Generic.List`1 + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 02 00 00 00 01 02 00 00 ) + .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) + .method public specialname rtspecialname + instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void class [runtime]System.Collections.Generic.List`1::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig specialname + instance string get_FirstItem() cil managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) + + .maxstack 4 + .locals init (class MyTestModule/DerivedWhichAllowsNull V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldarg.0 + IL_0003: ldc.i4.0 + IL_0004: tail. + IL_0006: callvirt instance !0 class [runtime]System.Collections.Generic.List`1::get_Item(int32) + IL_000b: ret + } + + .property instance string FirstItem() + { + .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) + .get instance string MyTestModule/DerivedWhichAllowsNull::get_FirstItem() + } + } + + .class auto ansi serializable nested public DerivedWithoutNull + extends class [runtime]System.Collections.Generic.List`1 + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) + .method public specialname rtspecialname + instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void class [runtime]System.Collections.Generic.List`1::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig specialname + instance string get_FirstItem() cil managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) + + .maxstack 4 + .locals init (class MyTestModule/DerivedWithoutNull V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldarg.0 + IL_0003: ldc.i4.0 + IL_0004: tail. + IL_0006: callvirt instance !0 class [runtime]System.Collections.Generic.List`1::get_Item(int32) + IL_000b: ret + } + + .property instance string FirstItem() + { + .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) + .get instance string MyTestModule/DerivedWithoutNull::get_FirstItem() + } + } + + .class interface abstract auto ansi serializable nested public beforefieldinit ICanGetAnything`1 + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) + .param type T + .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) + .method public hidebysig abstract virtual + instance !T Get() cil managed + { + } + + } + + .class auto ansi serializable nested public MyClassImplementingTheSameInterface + extends [runtime]System.Object + implements class MyTestModule/ICanGetAnything`1>, + class MyTestModule/ICanGetAnything`1>>, + class MyTestModule/ICanGetAnything`1 + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) + .interfaceimpl type class MyTestModule/ICanGetAnything`1> + .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 02 00 00 ) + .interfaceimpl type class MyTestModule/ICanGetAnything`1 + .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 02 00 00 00 01 02 00 00 ) + .method public specialname rtspecialname + instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method private hidebysig newslot virtual + instance string 'MyTestModule.ICanGetAnything.Get'() cil managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) + .override method instance !0 class MyTestModule/ICanGetAnything`1::Get() + + .maxstack 3 + .locals init (class MyTestModule/MyClassImplementingTheSameInterface V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldnull + IL_0003: ret + } + + .method private hidebysig newslot virtual + instance class [runtime]System.Collections.Generic.List`1> + 'MyTestModule.ICanGetAnything>>.Get'() cil managed + { + .override method instance !0 class MyTestModule/ICanGetAnything`1>>::Get() + + .maxstack 3 + .locals init (class MyTestModule/MyClassImplementingTheSameInterface V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: newobj instance void class [runtime]System.Collections.Generic.List`1>::.ctor() + IL_0007: ret + } + + .method private hidebysig newslot virtual + instance class [runtime]System.Collections.Generic.List`1 + 'MyTestModule.ICanGetAnything>.Get'() cil managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) + .override method instance !0 class MyTestModule/ICanGetAnything`1>::Get() + + .maxstack 3 + .locals init (class MyTestModule/MyClassImplementingTheSameInterface V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldnull + IL_0003: ret + } + + } + +} + +.class private abstract auto ansi sealed ''.$MyTestModule + extends [runtime]System.Object +{ +} + +.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute + extends [runtime]System.Attribute +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field public uint8[] NullableFlags + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public specialname rtspecialname + instance void .ctor(uint8 scalarByteValue) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Attribute::.ctor() + IL_0006: ldarg.0 + IL_0007: ldc.i4.1 + IL_0008: newarr [runtime]System.Byte + IL_000d: dup + IL_000e: ldc.i4.0 + IL_000f: ldarg.1 + IL_0010: stelem.i1 + IL_0011: stfld uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags + IL_0016: ret + } + + .method public specialname rtspecialname + instance void .ctor(uint8[] NullableFlags) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Attribute::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags + IL_000d: ret + } + +} + +.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute + extends [runtime]System.Attribute +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field public uint8 Flag + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public specialname rtspecialname + instance void .ctor(uint8 Flag) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Attribute::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag + IL_000d: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullableInheritance.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullableInheritance.fs.il.netcore.bsl new file mode 100644 index 00000000000..6d3e0775b13 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullableInheritance.fs.il.netcore.bsl @@ -0,0 +1,209 @@ + + + + + +.assembly extern runtime { } +.assembly extern System.Collections +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) + .ver 8:0:0:0 +} +.assembly extern FSharp.Core { } +.assembly assembly +{ + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.dll + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed MyTestModule + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public DerivedWhichAllowsNull + extends class [System.Collections]System.Collections.Generic.List`1 + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 02 00 00 00 01 02 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) + .method public specialname rtspecialname + instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void class [System.Collections]System.Collections.Generic.List`1::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig specialname + instance string get_FirstItem() cil managed + { + .param [0] + .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) + + .maxstack 4 + .locals init (class MyTestModule/DerivedWhichAllowsNull V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldarg.0 + IL_0003: ldc.i4.0 + IL_0004: tail. + IL_0006: callvirt instance !0 class [System.Collections]System.Collections.Generic.List`1::get_Item(int32) + IL_000b: ret + } + + .property instance string FirstItem() + { + .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) + .get instance string MyTestModule/DerivedWhichAllowsNull::get_FirstItem() + } + } + + .class auto ansi serializable nested public DerivedWithoutNull + extends class [System.Collections]System.Collections.Generic.List`1 + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) + .method public specialname rtspecialname + instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void class [System.Collections]System.Collections.Generic.List`1::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig specialname + instance string get_FirstItem() cil managed + { + + .maxstack 4 + .locals init (class MyTestModule/DerivedWithoutNull V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldarg.0 + IL_0003: ldc.i4.0 + IL_0004: tail. + IL_0006: callvirt instance !0 class [System.Collections]System.Collections.Generic.List`1::get_Item(int32) + IL_000b: ret + } + + .property instance string FirstItem() + { + .get instance string MyTestModule/DerivedWithoutNull::get_FirstItem() + } + } + + .class interface abstract auto ansi serializable nested public beforefieldinit ICanGetAnything`1 + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) + .param type T + .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) + .method public hidebysig abstract virtual + instance !T Get() cil managed + { + } + + } + + .class auto ansi serializable nested public MyClassImplementingTheSameInterface + extends [runtime]System.Object + implements class MyTestModule/ICanGetAnything`1>, + class MyTestModule/ICanGetAnything`1>>, + class MyTestModule/ICanGetAnything`1 + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) + .interfaceimpl type class MyTestModule/ICanGetAnything`1> + .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 02 00 00 ) + .interfaceimpl type class MyTestModule/ICanGetAnything`1 + .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 02 00 00 00 01 02 00 00 ) + .method public specialname rtspecialname + instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method private hidebysig newslot virtual + instance string 'MyTestModule.ICanGetAnything.Get'() cil managed + { + .param [0] + .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) + .override method instance !0 class MyTestModule/ICanGetAnything`1::Get() + + .maxstack 3 + .locals init (class MyTestModule/MyClassImplementingTheSameInterface V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldnull + IL_0003: ret + } + + .method private hidebysig newslot virtual + instance class [System.Collections]System.Collections.Generic.List`1> + 'MyTestModule.ICanGetAnything>>.Get'() cil managed + { + .override method instance !0 class MyTestModule/ICanGetAnything`1>>::Get() + + .maxstack 3 + .locals init (class MyTestModule/MyClassImplementingTheSameInterface V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: newobj instance void class [System.Collections]System.Collections.Generic.List`1>::.ctor() + IL_0007: ret + } + + .method private hidebysig newslot virtual + instance class [System.Collections]System.Collections.Generic.List`1 + 'MyTestModule.ICanGetAnything>.Get'() cil managed + { + .param [0] + .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) + .override method instance !0 class MyTestModule/ICanGetAnything`1>::Get() + + .maxstack 3 + .locals init (class MyTestModule/MyClassImplementingTheSameInterface V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldnull + IL_0003: ret + } + + } + +} + +.class private abstract auto ansi sealed ''.$MyTestModule + extends [runtime]System.Object +{ +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs index 0c9774032e8..c7bc6a47755 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs @@ -74,6 +74,11 @@ let ``Generic struct DU`` compilation = compilation |> verifyCompilation DoNotOptimize +[] +let ``Nullable inheritance`` compilation = + compilation + |> verifyCompilation DoNotOptimize + module Interop = open System.IO diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/FileContentMappingTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/FileContentMappingTests.fs index 279bb55e3dc..12f171de5fa 100644 --- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/FileContentMappingTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/FileContentMappingTests.fs @@ -122,17 +122,36 @@ module B = C | [ TopLevelNamespace "" [ PrefixedIdentifier "C" ] ] -> Assert.Pass() | content -> Assert.Fail($"Unexpected content: {content}") -[] -let ``Invalid nested module should just be ignored`` () = - let content = - getContent - false - """ -module A -module B.C -""" +module InvalidSyntax = - match content with - | [ TopLevelNamespace "" [] ] -> Assert.Pass() - | content -> Assert.Fail($"Unexpected content: {content}") + [] + let ``Nested module`` () = + let content = + getContent + false + """ + module A + + module B.C + """ + + match content with + | [ TopLevelNamespace "" [] ] -> Assert.Pass() + | content -> Assert.Fail($"Unexpected content: {content}") + + + [] + let ``Module above namespace`` () = + let content = + getContent + false + """ + module + + namespace A.B.C + """ + + match content with + | [ TopLevelNamespace "" [] ] -> Assert.Pass() + | content -> Assert.Fail($"Unexpected content: {content}") diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl index 954fca3437d..7dd8098aeb9 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl @@ -7,6 +7,22 @@ ! AssemblyReference: System.Reflection.Emit.ILGeneration ! AssemblyReference: System.Reflection.Metadata ! AssemblyReference: netstandard +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: j__TPar IntImplIdx +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: j__TPar get_IntImplIdx() +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: j__TPar IntfIdx +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: j__TPar get_IntfIdx() +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: j__TPar TypeIdx +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: j__TPar get_TypeIdx() +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Boolean Equals(<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]) +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Boolean Equals(System.Object) +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Int32 CompareTo(<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]) +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Int32 CompareTo(System.Object) +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Int32 CompareTo(System.Object, System.Collections.IComparer) +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Int32 GetHashCode() +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Int32 GetHashCode(System.Collections.IEqualityComparer) +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: System.String ToString() +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Void .ctor(j__TPar, j__TPar, j__TPar) FSharp.Compiler.AbstractIL.IL+ILArgConvention+Tags: Int32 CDecl FSharp.Compiler.AbstractIL.IL+ILArgConvention+Tags: Int32 Default FSharp.Compiler.AbstractIL.IL+ILArgConvention+Tags: Int32 FastCall @@ -1540,7 +1556,7 @@ FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILPropertyDefs Properties FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILPropertyDefs get_Properties() FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILSecurityDecls SecurityDecls FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILSecurityDecls get_SecurityDecls() -FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDef With(Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Reflection.TypeAttributes], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILTypeDefLayout], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType]], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef]], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILType]], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILMethodDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILTypeDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILFieldDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILMethodImplDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILEventDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILPropertyDefs], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILAttributes], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILSecurityDecls]) +FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDef With(Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Reflection.TypeAttributes], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILTypeDefLayout], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType]], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef]], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILType]], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILMethodDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILTypeDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILFieldDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILMethodImplDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILEventDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILPropertyDefs], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILAttributes], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILSecurityDecls], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.AbstractIL.IL+ILAttributesStored,System.Int32]]]]) FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDefAccess Access FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDefAccess get_Access() FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDefLayout Layout @@ -1555,12 +1571,14 @@ FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Collections.FSharpList FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType] get_Implements() FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILType] Extends FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILType] get_Extends() +FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.AbstractIL.IL+ILAttributesStored,System.Int32]]] ImplementsCustomAttrs +FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.AbstractIL.IL+ILAttributesStored,System.Int32]]] get_ImplementsCustomAttrs() FSharp.Compiler.AbstractIL.IL+ILTypeDef: System.Reflection.TypeAttributes Attributes FSharp.Compiler.AbstractIL.IL+ILTypeDef: System.Reflection.TypeAttributes get_Attributes() FSharp.Compiler.AbstractIL.IL+ILTypeDef: System.String Name FSharp.Compiler.AbstractIL.IL+ILTypeDef: System.String ToString() FSharp.Compiler.AbstractIL.IL+ILTypeDef: System.String get_Name() -FSharp.Compiler.AbstractIL.IL+ILTypeDef: Void .ctor(System.String, System.Reflection.TypeAttributes, ILTypeDefLayout, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILType], ILMethodDefs, ILTypeDefs, ILFieldDefs, ILMethodImplDefs, ILEventDefs, ILPropertyDefs, Boolean, ILSecurityDecls, ILAttributes) +FSharp.Compiler.AbstractIL.IL+ILTypeDef: Void .ctor(System.String, System.Reflection.TypeAttributes, ILTypeDefLayout, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.AbstractIL.IL+ILAttributesStored,System.Int32]]], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILType], ILMethodDefs, ILTypeDefs, ILFieldDefs, ILMethodImplDefs, ILEventDefs, ILPropertyDefs, Boolean, ILSecurityDecls, ILAttributes) FSharp.Compiler.AbstractIL.IL+ILTypeDefAccess+Nested: ILMemberAccess Item FSharp.Compiler.AbstractIL.IL+ILTypeDefAccess+Nested: ILMemberAccess get_Item() FSharp.Compiler.AbstractIL.IL+ILTypeDefAccess+Tags: Int32 Nested diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl index 954fca3437d..7dd8098aeb9 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl @@ -7,6 +7,22 @@ ! AssemblyReference: System.Reflection.Emit.ILGeneration ! AssemblyReference: System.Reflection.Metadata ! AssemblyReference: netstandard +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: j__TPar IntImplIdx +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: j__TPar get_IntImplIdx() +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: j__TPar IntfIdx +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: j__TPar get_IntfIdx() +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: j__TPar TypeIdx +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: j__TPar get_TypeIdx() +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Boolean Equals(<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]) +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Boolean Equals(System.Object) +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Int32 CompareTo(<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]) +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Int32 CompareTo(System.Object) +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Int32 CompareTo(System.Object, System.Collections.IComparer) +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Int32 GetHashCode() +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Int32 GetHashCode(System.Collections.IEqualityComparer) +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: System.String ToString() +<>f__AnonymousType10003411232265`3[j__TPar,j__TPar,j__TPar]: Void .ctor(j__TPar, j__TPar, j__TPar) FSharp.Compiler.AbstractIL.IL+ILArgConvention+Tags: Int32 CDecl FSharp.Compiler.AbstractIL.IL+ILArgConvention+Tags: Int32 Default FSharp.Compiler.AbstractIL.IL+ILArgConvention+Tags: Int32 FastCall @@ -1540,7 +1556,7 @@ FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILPropertyDefs Properties FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILPropertyDefs get_Properties() FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILSecurityDecls SecurityDecls FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILSecurityDecls get_SecurityDecls() -FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDef With(Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Reflection.TypeAttributes], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILTypeDefLayout], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType]], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef]], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILType]], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILMethodDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILTypeDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILFieldDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILMethodImplDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILEventDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILPropertyDefs], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILAttributes], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILSecurityDecls]) +FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDef With(Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Reflection.TypeAttributes], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILTypeDefLayout], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType]], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef]], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILType]], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILMethodDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILTypeDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILFieldDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILMethodImplDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILEventDefs], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILPropertyDefs], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILAttributes], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILSecurityDecls], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.AbstractIL.IL+ILAttributesStored,System.Int32]]]]) FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDefAccess Access FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDefAccess get_Access() FSharp.Compiler.AbstractIL.IL+ILTypeDef: ILTypeDefLayout Layout @@ -1555,12 +1571,14 @@ FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Collections.FSharpList FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType] get_Implements() FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILType] Extends FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILType] get_Extends() +FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.AbstractIL.IL+ILAttributesStored,System.Int32]]] ImplementsCustomAttrs +FSharp.Compiler.AbstractIL.IL+ILTypeDef: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.AbstractIL.IL+ILAttributesStored,System.Int32]]] get_ImplementsCustomAttrs() FSharp.Compiler.AbstractIL.IL+ILTypeDef: System.Reflection.TypeAttributes Attributes FSharp.Compiler.AbstractIL.IL+ILTypeDef: System.Reflection.TypeAttributes get_Attributes() FSharp.Compiler.AbstractIL.IL+ILTypeDef: System.String Name FSharp.Compiler.AbstractIL.IL+ILTypeDef: System.String ToString() FSharp.Compiler.AbstractIL.IL+ILTypeDef: System.String get_Name() -FSharp.Compiler.AbstractIL.IL+ILTypeDef: Void .ctor(System.String, System.Reflection.TypeAttributes, ILTypeDefLayout, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILType], ILMethodDefs, ILTypeDefs, ILFieldDefs, ILMethodImplDefs, ILEventDefs, ILPropertyDefs, Boolean, ILSecurityDecls, ILAttributes) +FSharp.Compiler.AbstractIL.IL+ILTypeDef: Void .ctor(System.String, System.Reflection.TypeAttributes, ILTypeDefLayout, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILType], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.AbstractIL.IL+ILAttributesStored,System.Int32]]], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.AbstractIL.IL+ILType], ILMethodDefs, ILTypeDefs, ILFieldDefs, ILMethodImplDefs, ILEventDefs, ILPropertyDefs, Boolean, ILSecurityDecls, ILAttributes) FSharp.Compiler.AbstractIL.IL+ILTypeDefAccess+Nested: ILMemberAccess Item FSharp.Compiler.AbstractIL.IL+ILTypeDefAccess+Nested: ILMemberAccess get_Item() FSharp.Compiler.AbstractIL.IL+ILTypeDefAccess+Tags: Int32 Nested diff --git a/tests/benchmarks/FCSBenchmarks/BenchmarkComparison/HistoricalBenchmark.Runner/HistoricalBenchmark.Runner.fsproj b/tests/benchmarks/FCSBenchmarks/BenchmarkComparison/HistoricalBenchmark.Runner/HistoricalBenchmark.Runner.fsproj index 13add70323f..fe6d95f9050 100644 --- a/tests/benchmarks/FCSBenchmarks/BenchmarkComparison/HistoricalBenchmark.Runner/HistoricalBenchmark.Runner.fsproj +++ b/tests/benchmarks/FCSBenchmarks/BenchmarkComparison/HistoricalBenchmark.Runner/HistoricalBenchmark.Runner.fsproj @@ -4,6 +4,7 @@ net8.0 true HistoricalBenchmark.Utilities + $(NoWarn);NETSDK1206 diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs index 528557fa3d7..b7ed2a4b78d 100644 --- a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs @@ -225,7 +225,7 @@ type TestProjectType = [] [] [] -[] +[] type TransparentCompilerBenchmark() = let size = 30 diff --git a/tests/scripts/update-baselines.fsx b/tests/scripts/update-baselines.fsx index 06e9c13ef80..6cc8631d898 100644 --- a/tests/scripts/update-baselines.fsx +++ b/tests/scripts/update-baselines.fsx @@ -1,13 +1,13 @@ open System open System.IO -// this script is usefull for tests using a .bsl file (baseline) containing expected compiler output +// this script is useful for tests using a .bsl file (baseline) containing expected compiler output // which is matched against .vserr or .err file aside once the test has run // the script replaces all the .bsl/.bslpp with either .err or .vserr let diff path1 path2 = let result = System.Text.StringBuilder() - let append s = result.AppendLine s |> ignore + let append (s: string) = result.AppendLine s |> ignore if not <| File.Exists(path1) then failwithf "Invalid path %s" path1 if not <| File.Exists(path2) then failwithf "Invalid path %s" path2 diff --git a/tests/service/ModuleReaderCancellationTests.fs b/tests/service/ModuleReaderCancellationTests.fs index a401c637fe6..930791b0ca6 100644 --- a/tests/service/ModuleReaderCancellationTests.fs +++ b/tests/service/ModuleReaderCancellationTests.fs @@ -115,7 +115,7 @@ type PreTypeDefData = let typeAttributes = TypeAttributes.Public let customAttrs = mkILCustomAttrs [] - ILTypeDef(this.Name, typeAttributes, ILTypeDefLayout.Auto, [], [], + ILTypeDef(this.Name, typeAttributes, ILTypeDefLayout.Auto, [], None, [], None, methodsDefs, mkILTypeDefs [], mkILFields [], emptyILMethodImpls, mkILEvents [], mkILProperties [], false, emptyILSecurityDecls, customAttrs) diff --git a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs index c0682607360..6e3de8133f1 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs @@ -447,7 +447,7 @@ module private CheckerExtensions = ) = cancellableTask { - if document.Project.UseTransparentCompiler then + if checker.UsesTransparentCompiler then return! checker.ParseAndCheckDocumentUsingTransparentCompiler(document, options, userOpName) else let allowStaleResults = diff --git a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveUnnecessaryParenthesesTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveUnnecessaryParenthesesTests.fs index 69d6456e378..cd3bbdd2bfc 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveUnnecessaryParenthesesTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveUnnecessaryParenthesesTests.fs @@ -800,6 +800,24 @@ in x "$\"{(id 3)}\"", "$\"{id 3}\"" "$\"{(x)}\"", "$\"{x}\"" + "$\"{(if true then 1 else 0)}\"", "$\"{if true then 1 else 0}\"" + "$\"{(if true then 1 else 0):N0}\"", "$\"{(if true then 1 else 0):N0}\"" + "$\"{(if true then 1 else 0),-3}\"", "$\"{(if true then 1 else 0),-3}\"" + "$\"{(match () with () -> 1):N0}\"", "$\"{(match () with () -> 1):N0}\"" + "$\"{(match () with () -> 1),-3}\"", "$\"{(match () with () -> 1),-3}\"" + "$\"{(try () with _ -> 1):N0}\"", "$\"{(try () with _ -> 1):N0}\"" + "$\"{(try () with _ -> 1),-3}\"", "$\"{(try () with _ -> 1),-3}\"" + "$\"{(try 1 finally ()):N0}\"", "$\"{(try 1 finally ()):N0}\"" + "$\"{(try 1 finally ()),-3}\"", "$\"{(try 1 finally ()),-3}\"" + "$\"{(let x = 3 in x):N0}\"", "$\"{(let x = 3 in x):N0}\"" + "$\"{(let x = 3 in x),-3}\"", "$\"{(let x = 3 in x),-3}\"" + "$\"{(do (); 3):N0}\"", "$\"{(do (); 3):N0}\"" + "$\"{(do (); 3),-3}\"", "$\"{(do (); 3),-3}\"" + "$\"{(x <- 3):N0}\"", "$\"{(x <- 3):N0}\"" + "$\"{(x <- 3),-3}\"", "$\"{(x <- 3),-3}\"" + "$\"{(1, 2):N0}\"", "$\"{(1, 2):N0}\"" + "$\"{(1, 2),-3}\"", "$\"{(1, 2),-3}\"" + """ $"{(3 + LanguagePrimitives.GenericZero):N0}" """,