From 4ba648bdabf334eef698c19cbc512041a76be511 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 14 Mar 2024 13:19:52 +0100 Subject: [PATCH 01/11] mkAppTy resolved --- src/Compiler/Checking/AttributeChecking.fs | 2 +- .../Checking/AugmentWithHashCompare.fs | 8 ++-- src/Compiler/Checking/CheckDeclarations.fs | 12 +++--- src/Compiler/Checking/CheckExpressions.fs | 16 ++++---- src/Compiler/Checking/CheckPatterns.fs | 2 +- src/Compiler/Checking/ConstraintSolver.fs | 16 ++++---- src/Compiler/Checking/NameResolution.fs | 4 +- .../Checking/PatternMatchCompilation.fs | 4 +- src/Compiler/Checking/QuotationTranslator.fs | 2 +- src/Compiler/Checking/TypeHierarchy.fs | 4 +- src/Compiler/CodeGen/IlxGen.fs | 8 ++-- src/Compiler/Optimize/Optimizer.fs | 2 +- src/Compiler/Symbols/Exprs.fs | 38 +++++++++---------- src/Compiler/TypedTree/TypedTreeOps.fs | 14 +++---- src/Compiler/TypedTree/TypedTreeOps.fsi | 2 +- 15 files changed, 67 insertions(+), 67 deletions(-) diff --git a/src/Compiler/Checking/AttributeChecking.fs b/src/Compiler/Checking/AttributeChecking.fs index 79dc9402014..d550aaccba4 100644 --- a/src/Compiler/Checking/AttributeChecking.fs +++ b/src/Compiler/Checking/AttributeChecking.fs @@ -540,7 +540,7 @@ let IsSecurityAttribute (g: TcGlobals) amap (casmap : IDictionary) match casmap.TryGetValue tcs with | true, c -> c | _ -> - let exists = ExistsInEntireHierarchyOfType (fun t -> typeEquiv g t (mkAppTy attr.TyconRef [])) g amap m AllowMultiIntfInstantiations.Yes (mkAppTy tcref []) + let exists = ExistsInEntireHierarchyOfType (fun t -> typeEquiv g t (mkWoNullAppTy attr.TyconRef [])) g amap m AllowMultiIntfInstantiations.Yes (mkWoNullAppTy tcref []) casmap[tcs] <- exists exists | ValueNone -> false diff --git a/src/Compiler/Checking/AugmentWithHashCompare.fs b/src/Compiler/Checking/AugmentWithHashCompare.fs index d3e9fb1d42d..cfaece0bfb4 100644 --- a/src/Compiler/Checking/AugmentWithHashCompare.fs +++ b/src/Compiler/Checking/AugmentWithHashCompare.fs @@ -20,7 +20,7 @@ let mkIComparableCompareToSlotSig (g: TcGlobals) = let mkGenericIComparableCompareToSlotSig (g: TcGlobals) ty = TSlotSig( "CompareTo", - (mkAppTy g.system_GenericIComparable_tcref [ ty ]), + (mkWoNullAppTy g.system_GenericIComparable_tcref [ ty ]), [], [], [ [ TSlotParam(Some("obj"), ty, false, false, false, []) ] ], @@ -44,7 +44,7 @@ let mkIStructuralComparableCompareToSlotSig (g: TcGlobals) = let mkGenericIEquatableEqualsSlotSig (g: TcGlobals) ty = TSlotSig( "Equals", - (mkAppTy g.system_GenericIEquatable_tcref [ ty ]), + (mkWoNullAppTy g.system_GenericIEquatable_tcref [ ty ]), [], [], [ [ TSlotParam(Some("obj"), ty, false, false, false, []) ] ], @@ -414,7 +414,7 @@ let mkExnEquality (g: TcGlobals) exnref (exnc: Tycon) = let cases = [ - mkCase (DecisionTreeTest.IsInst(g.exn_ty, mkAppTy exnref []), mbuilder.AddResultTarget(expr)) + mkCase (DecisionTreeTest.IsInst(g.exn_ty, mkWoNullAppTy exnref []), mbuilder.AddResultTarget(expr)) ] let dflt = Some(mbuilder.AddResultTarget(mkFalse g m)) @@ -445,7 +445,7 @@ let mkExnEqualityWithComparer g exnref (exnc: Tycon) (_thisv, thise) thatobje (t let cases = [ - mkCase (DecisionTreeTest.IsInst(g.exn_ty, mkAppTy exnref []), mbuilder.AddResultTarget(expr)) + mkCase (DecisionTreeTest.IsInst(g.exn_ty, mkWoNullAppTy exnref []), mbuilder.AddResultTarget(expr)) ] let dflt = mbuilder.AddResultTarget(mkFalse g m) diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index a1e3ce8262b..8b61b5609c1 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -775,7 +775,7 @@ module AddAugmentationDeclarations = let tcaug = tycon.TypeContents let ty = if tcref.Deref.IsFSharpException then g.exn_ty else generalizedTyconRef g tcref let m = tycon.Range - let genericIComparableTy = mkAppTy g.system_GenericIComparable_tcref [ty] + let genericIComparableTy = mkWoNullAppTy g.system_GenericIComparable_tcref [ty] let hasExplicitIComparable = tycon.HasInterface g g.mk_IComparable_ty @@ -873,7 +873,7 @@ module AddAugmentationDeclarations = let vspec1, vspec2 = AugmentTypeDefinitions.MakeValsForEqualsAugmentation g tcref tcaug.SetEquals (mkLocalValRef vspec1, mkLocalValRef vspec2) if not tycon.IsFSharpException then - PublishInterface cenv env.DisplayEnv tcref m true (mkAppTy g.system_GenericIEquatable_tcref [ty]) + PublishInterface cenv env.DisplayEnv tcref m true (mkWoNullAppTy g.system_GenericIEquatable_tcref [ty]) PublishValueDefn cenv env ModuleOrMemberBinding vspec1 PublishValueDefn cenv env ModuleOrMemberBinding vspec2 AugmentTypeDefinitions.MakeBindingsForEqualsAugmentation g tycon @@ -1991,8 +1991,8 @@ let TcMutRecDefns_Phase2 (cenv: cenv) envInitial mBinds scopem mutRecNSInfo (env if (generatedCompareToValues && typeEquiv g intfTyR g.mk_IComparable_ty) || (generatedCompareToWithComparerValues && typeEquiv g intfTyR g.mk_IStructuralComparable_ty) || - (generatedCompareToValues && typeEquiv g intfTyR (mkAppTy g.system_GenericIComparable_tcref [ty])) || - (generatedHashAndEqualsWithComparerValues && typeEquiv g intfTyR (mkAppTy g.system_GenericIEquatable_tcref [ty])) || + (generatedCompareToValues && typeEquiv g intfTyR (mkWoNullAppTy g.system_GenericIComparable_tcref [ty])) || + (generatedHashAndEqualsWithComparerValues && typeEquiv g intfTyR (mkWoNullAppTy g.system_GenericIEquatable_tcref [ty])) || (generatedHashAndEqualsWithComparerValues && typeEquiv g intfTyR g.mk_IStructuralEquatable_ty) then errorR(Error(FSComp.SR.tcDefaultImplementationForInterfaceHasAlreadyBeenAdded(), intfTy.Range)) @@ -3316,7 +3316,7 @@ module EstablishTypeDefinitionCores = super |> Option.map (fun ty -> if isFunTy g ty then let a,b = destFunTy g ty - mkAppTy g.fastFunc_tcr [a; b] + mkWoNullAppTy g.fastFunc_tcr [a; b] else ty) // Publish the super type @@ -3715,7 +3715,7 @@ module EstablishTypeDefinitionCores = // validate ConditionalAttribute, should it be applied (it's only valid on a type if the type is an attribute type) match attrs |> List.tryFind (IsMatchingFSharpAttribute g g.attrib_ConditionalAttribute) with | Some _ -> - if not(ExistsInEntireHierarchyOfType (fun t -> typeEquiv g t (mkAppTy g.tcref_System_Attribute [])) g cenv.amap m AllowMultiIntfInstantiations.Yes thisTy) then + if not(ExistsInEntireHierarchyOfType (fun t -> typeEquiv g t (mkWoNullAppTy g.tcref_System_Attribute [])) g cenv.amap m AllowMultiIntfInstantiations.Yes thisTy) then errorR(Error(FSComp.SR.tcConditionalAttributeUsage(), m)) | _ -> () diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 62625ac5f18..d6f39a7eda1 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -830,10 +830,10 @@ let TcConst (cenv: cenv) (overallTy: TType) m env synConst = let measureTy = match synConst with | SynConst.Measure(synMeasure = SynMeasure.Anon _) -> - (mkAppTy tcr [TType_measure (Measure.Var (NewAnonTypar (TyparKind.Measure, m, TyparRigidity.Anon, (if iszero then TyparStaticReq.None else TyparStaticReq.HeadType), TyparDynamicReq.No)))]) + (mkWoNullAppTy tcr [TType_measure (Measure.Var (NewAnonTypar (TyparKind.Measure, m, TyparRigidity.Anon, (if iszero then TyparStaticReq.None else TyparStaticReq.HeadType), TyparDynamicReq.No)))]) - | SynConst.Measure(synMeasure = ms) -> mkAppTy tcr [TType_measure (tcMeasure ms)] - | _ -> mkAppTy tcr [TType_measure Measure.One] + | SynConst.Measure(synMeasure = ms) -> mkWoNullAppTy tcr [TType_measure (tcMeasure ms)] + | _ -> mkWoNullAppTy tcr [TType_measure Measure.One] unif measureTy let expandedMeasurablesEnabled = @@ -853,7 +853,7 @@ let TcConst (cenv: cenv) (overallTy: TType) m env synConst = unif g.float_ty Const.Double f | SynConst.Decimal f -> - unif (mkAppTy g.decimal_tcr []) + unif (mkWoNullAppTy g.decimal_tcr []) Const.Decimal f | SynConst.SByte i -> unif g.sbyte_ty @@ -3419,7 +3419,7 @@ let AnalyzeArbitraryExprAsEnumerable (cenv: cenv) (env: TcEnv) localAlloc m expr match probe exprTyAsSeq with | Some res -> res | None -> - let ienumerable = mkAppTy g.tcref_System_Collections_IEnumerable [] + let ienumerable = mkWoNullAppTy g.tcref_System_Collections_IEnumerable [] match probe ienumerable with | Some res -> res | None -> @@ -5025,7 +5025,7 @@ and TcProvidedTypeApp (cenv: cenv) env tpenv tcref args m = // We put the type name check after the 'isDirectReferenceToGenerated' check because we need the 'isDirectReferenceToGenerated' error to be shown for generated types checkTypeName() if hasNoArgs then - mkAppTy tcref [], tpenv + mkWoNullAppTy tcref [], tpenv else let ty = Import.ImportProvidedType cenv.amap m providedTypeAfterStaticArguments ty, tpenv @@ -7642,7 +7642,7 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, withExprOpt, synRecdFields, m | None -> [] | Some(tinst, tcref, _, fldsList) -> - let gtyp = mkAppTy tcref tinst + let gtyp = mkWoNullAppTy tcref tinst UnifyTypes cenv env mWholeExpr overallTy gtyp [ for n, v in fldsList do @@ -12105,7 +12105,7 @@ and TcLetrecBinding | None -> let reqdThisValTy = if isByrefTy g reqdThisValTy then destByrefTy g reqdThisValTy else reqdThisValTy let enclosingTyconRef = tcrefOfAppTy g reqdThisValTy - reqdThisValTy, (mkAppTy enclosingTyconRef (List.map mkTyparTy enclosingDeclaredTypars)), vspec.Range + reqdThisValTy, (mkWoNullAppTy enclosingTyconRef (List.map mkTyparTy enclosingDeclaredTypars)), vspec.Range | Some thisVal -> reqdThisValTy, thisVal.Type, thisVal.Range if not (AddCxTypeEqualsTypeUndoIfFailed envRec.DisplayEnv cenv.css rangeForCheck actualThisValTy reqdThisValTy) then diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index 896df82f844..fbf48dcdf2d 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -442,7 +442,7 @@ and TcRecordPat warnOnUpper cenv env vFlags patEnv ty fieldPats m = | None -> (fun _ -> TPat_error m), patEnv | Some(tinst, tcref, fldsmap, _fldsList) -> - let gtyp = mkAppTy tcref tinst + let gtyp = mkWoNullAppTy tcref tinst let inst = List.zip (tcref.Typars m) tinst UnifyTypes cenv env m ty gtyp diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index cfae752df80..72530a44de4 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -1536,7 +1536,7 @@ and DepthCheck ndeep m = and SolveDimensionlessNumericType (csenv: ConstraintSolverEnv) ndeep m2 trace ty = match getMeasureOfType csenv.g ty with | Some (tcref, _) -> - SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace ty (mkAppTy tcref [TType_measure Measure.One]) + SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace ty (mkWoNullAppTy tcref [TType_measure Measure.One]) | None -> CompleteD @@ -1641,8 +1641,8 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload match getMeasureOfType g argTy1 with | Some (tcref, ms1) -> let ms2 = freshMeasure () - do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 (mkAppTy tcref [TType_measure ms2]) - do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkAppTy tcref [TType_measure (Measure.Prod(ms1, if nm = "op_Multiply" then ms2 else Measure.Inv ms2))]) + do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 (mkWoNullAppTy tcref [TType_measure ms2]) + do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure (Measure.Prod(ms1, if nm = "op_Multiply" then ms2 else Measure.Inv ms2))]) return TTraitBuiltIn | _ -> @@ -1650,8 +1650,8 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload match getMeasureOfType g argTy2 with | Some (tcref, ms2) -> let ms1 = freshMeasure () - do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy1 (mkAppTy tcref [TType_measure ms1]) - do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkAppTy tcref [TType_measure (Measure.Prod(ms1, if nm = "op_Multiply" then ms2 else Measure.Inv ms2))]) + do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy1 (mkWoNullAppTy tcref [TType_measure ms1]) + do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure (Measure.Prod(ms1, if nm = "op_Multiply" then ms2 else Measure.Inv ms2))]) return TTraitBuiltIn | _ -> @@ -1785,8 +1785,8 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload match getMeasureOfType g argTy1 with | Some (tcref, _) -> let ms1 = freshMeasure () - do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy1 (mkAppTy tcref [TType_measure (Measure.Prod (ms1, ms1))]) - do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkAppTy tcref [TType_measure ms1]) + do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy1 (mkWoNullAppTy tcref [TType_measure (Measure.Prod (ms1, ms1))]) + do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure ms1]) return TTraitBuiltIn | None -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1 @@ -1838,7 +1838,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 argTy1 match getMeasureOfType g argTy1 with | None -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1 - | Some (tcref, _) -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkAppTy tcref [TType_measure Measure.One]) + | Some (tcref, _) -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure Measure.One]) return TTraitBuiltIn | _ -> diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 6c85319ddc2..f6ca36614a6 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -1107,7 +1107,7 @@ let GetNestedTyconRefsOfType (infoReader: InfoReader) (amap: Import.ImportMap) ( let MakeNestedType (ncenv: NameResolver) (tinst: TType list) m (tcrefNested: TyconRef) = let tps = match tcrefNested.Typars m with [] -> [] | l -> List.skip tinst.Length l let tinstNested = ncenv.InstantiationGenerator m tps - mkAppTy tcrefNested (tinst @ tinstNested) + mkWoNullAppTy tcrefNested (tinst @ tinstNested) /// Get all the accessible nested types of an existing type. let GetNestedTypesOfType (ad, ncenv: NameResolver, optFilter, staticResInfo, checkForGenerated, m) ty = @@ -3400,7 +3400,7 @@ let rec ResolvePatternLongIdentPrim sink (ncenv: NameResolver) fullyQualified wa | tcref :: _ when tcref.IsUnionTycon -> let res = ResolutionInfo.Empty.AddEntity (id.idRange, tcref) ResolutionInfo.SendEntityPathToSink (sink, ncenv, nenv, ItemOccurence.Pattern, ad, res, ResultTyparChecker(fun () -> true)) - Item.Types (id.idText, [ mkAppTy tcref [] ]) + Item.Types (id.idText, [ mkWoNullAppTy tcref [] ]) | _ -> match ResolveLongIdentAsModuleOrNamespace sink ncenv.amap id.idRange true fullyQualified nenv ad id [] false ShouldNotifySink.Yes with | Result ((_, mref, _) :: _) -> diff --git a/src/Compiler/Checking/PatternMatchCompilation.fs b/src/Compiler/Checking/PatternMatchCompilation.fs index 4e8ced8fadb..ed786b941a5 100644 --- a/src/Compiler/Checking/PatternMatchCompilation.fs +++ b/src/Compiler/Checking/PatternMatchCompilation.fs @@ -611,7 +611,7 @@ let getDiscrimOfPattern (g: TcGlobals) tpinst t = | TPat_isinst (srcTy, tgtTy, _, _m) -> Some(DecisionTreeTest.IsInst (instType tpinst srcTy, instType tpinst tgtTy)) | TPat_exnconstr(tcref, _, _m) -> - Some(DecisionTreeTest.IsInst (g.exn_ty, mkAppTy tcref [])) + Some(DecisionTreeTest.IsInst (g.exn_ty, mkWoNullAppTy tcref [])) | TPat_const (c, _m) -> Some(DecisionTreeTest.Const c) | TPat_unioncase (c, tyargs', _, _m) -> @@ -1520,7 +1520,7 @@ let CompilePatternBasic | TPat_exnconstr (ecref, argpats, _) -> let srcTy1 = g.exn_ty - let tgtTy1 = mkAppTy ecref [] + let tgtTy1 = mkWoNullAppTy ecref [] if taken |> List.exists (discrimsEq g (DecisionTreeTest.IsInst (srcTy1, tgtTy1))) then [] else match discrim with diff --git a/src/Compiler/Checking/QuotationTranslator.fs b/src/Compiler/Checking/QuotationTranslator.fs index 8173c13755f..9c814c1da97 100644 --- a/src/Compiler/Checking/QuotationTranslator.fs +++ b/src/Compiler/Checking/QuotationTranslator.fs @@ -584,7 +584,7 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. | TOp.ExnConstr tcref, _, args -> let _rgtypR = ConvTyconRef cenv tcref m - let _typ = mkAppTy tcref [] + let _typ = mkWoNullAppTy tcref [] let parentTyconR = ConvTyconRef cenv tcref m let argTys = tcref |> recdFieldsOfExnDefRef |> List.map (fun rfld -> rfld.FormalType) let methArgTypesR = ConvTypes cenv env m argTys diff --git a/src/Compiler/Checking/TypeHierarchy.fs b/src/Compiler/Checking/TypeHierarchy.fs index a19d3c4d3b5..ea0d9e93970 100644 --- a/src/Compiler/Checking/TypeHierarchy.fs +++ b/src/Compiler/Checking/TypeHierarchy.fs @@ -201,10 +201,10 @@ and GetImmediateInterfacesOfMeasureAnnotatedType skipUnref g amap m ty reprTy = // However since F# 2.0 we have always reported these interfaces for all measure-annotated types. //if ExistsInInterfaceHierarchy (typeEquiv g (mkAppTy g.system_GenericIComparable_tcref [reprTy])) skipUnref g amap m ty then - mkAppTy g.system_GenericIComparable_tcref [ty] + mkWoNullAppTy g.system_GenericIComparable_tcref [ty] //if ExistsInInterfaceHierarchy (typeEquiv g (mkAppTy g.system_GenericIEquatable_tcref [reprTy])) skipUnref g amap m ty then - mkAppTy g.system_GenericIEquatable_tcref [ty] + mkWoNullAppTy g.system_GenericIEquatable_tcref [ty] ] // Check for any System.Numerics type in the interface hierarchy diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 92caba2e9a1..a29ff2f7357 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -1382,7 +1382,7 @@ let GetMethodSpecForMemberVal cenv (memberInfo: ValMemberInfo) (vref: ValRef) = if isCtor || cctor then ILType.Void else ilRetTy let ilTy = - GenType cenv m tyenvUnderTypars (mkAppTy parentTcref (List.map mkTyparTy ctps)) + GenType cenv m tyenvUnderTypars (mkWoNullAppTy parentTcref (List.map mkTyparTy ctps)) let nm = vref.CompiledName g.CompilerGlobalState @@ -2195,9 +2195,9 @@ type AnonTypeGenerationTable() = [ (g.mk_IStructuralComparable_ty, true, m) (g.mk_IComparable_ty, true, m) - (mkAppTy g.system_GenericIComparable_tcref [ ty ], true, m) + (mkWoNullAppTy g.system_GenericIComparable_tcref [ ty ], true, m) (g.mk_IStructuralEquatable_ty, true, m) - (mkAppTy g.system_GenericIEquatable_tcref [ ty ], true, m) + (mkWoNullAppTy g.system_GenericIEquatable_tcref [ ty ], true, m) ] let vspec1, vspec2 = AugmentTypeDefinitions.MakeValsForEqualsAugmentation g tcref @@ -5450,7 +5450,7 @@ and CommitCallSequel cenv eenv m cloc cgbuf mustGenerateUnitAfterCall sequel = and MakeNotSupportedExnExpr cenv eenv (argExpr, m) = let g = cenv.g - let ety = mkAppTy (g.FindSysTyconRef [ "System" ] "NotSupportedException") [] + let ety = mkWoNullAppTy (g.FindSysTyconRef [ "System" ] "NotSupportedException") [] let ilTy = GenType cenv m eenv.tyenv ety let mref = mkILCtorMethSpecForTy(ilTy, [ g.ilg.typ_String ]).MethodRef Expr.Op(TOp.ILCall(false, false, false, true, NormalValUse, false, false, mref, [], [], [ ety ]), [], [ argExpr ], m) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index fafb8184600..5af43b07801 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -2245,7 +2245,7 @@ let TryDetectQueryQuoteAndRun cenv (expr: Expr) = | QuerySelect g (qTy, _, resultElemTy, _, _) | QueryYield g (qTy, resultElemTy, _) | QueryYieldFrom g (qTy, resultElemTy, _) - when typeEquiv g qTy (mkAppTy g.tcref_System_Collections_IEnumerable []) -> + when typeEquiv g qTy (mkWoNullAppTy g.tcref_System_Collections_IEnumerable []) -> match tryRewriteToSeqCombinators g e with | Some newSource -> diff --git a/src/Compiler/Symbols/Exprs.fs b/src/Compiler/Symbols/Exprs.fs index dfdfb782e46..15b1bb2a3f6 100644 --- a/src/Compiler/Symbols/Exprs.fs +++ b/src/Compiler/Symbols/Exprs.fs @@ -327,7 +327,7 @@ module FSharpExprConvert = let ConvILTypeRefApp (cenv: SymbolEnv) m tref tyargs = let tcref = Import.ImportILTypeRef cenv.amap m tref - ConvType cenv (mkAppTy tcref tyargs) + ConvType cenv (mkWoNullAppTy tcref tyargs) let ConvUnionCaseRef cenv (ucref: UnionCaseRef) = FSharpUnionCase(cenv, ucref) @@ -378,7 +378,7 @@ module FSharpExprConvert = // Large lists | Expr.Op (TOp.UnionCase ucref, tyargs, [e1;e2], _) -> let mkR = ConvUnionCaseRef cenv ucref - let typR = ConvType cenv (mkAppTy ucref.TyconRef tyargs) + let typR = ConvType cenv (mkWoNullAppTy ucref.TyconRef tyargs) let e1R = ConvExpr cenv env e1 // tail recursive ConvExprLinear cenv env e2 (contF << (fun e2R -> E.NewUnionCase(typR, mkR, [e1R; e2R]) )) @@ -622,7 +622,7 @@ module FSharpExprConvert = match op, tyargs, args with | TOp.UnionCase ucref, _, _ -> let mkR = ConvUnionCaseRef cenv ucref - let typR = ConvType cenv (mkAppTy ucref.TyconRef tyargs) + let typR = ConvType cenv (mkWoNullAppTy ucref.TyconRef tyargs) let argsR = ConvExprs cenv env args E.NewUnionCase(typR, mkR, argsR) @@ -637,13 +637,13 @@ module FSharpExprConvert = E.NewTuple(tyR, argsR) | TOp.Recd (_, tcref), _, _ -> - let typR = ConvType cenv (mkAppTy tcref tyargs) + let typR = ConvType cenv (mkWoNullAppTy tcref tyargs) let argsR = ConvExprs cenv env args E.NewRecord(typR, argsR) | TOp.UnionCaseFieldGet (ucref, n), tyargs, [e1] -> let mkR = ConvUnionCaseRef cenv ucref - let typR = ConvType cenv (mkAppTy ucref.TyconRef tyargs) + let typR = ConvType cenv (mkWoNullAppTy ucref.TyconRef tyargs) let projR = FSharpField(cenv, ucref, n) E.UnionCaseGet(ConvExpr cenv env e1, typR, mkR, projR) @@ -653,7 +653,7 @@ module FSharpExprConvert = | TOp.UnionCaseFieldSet (ucref, n), tyargs, [e1;e2] -> let mkR = ConvUnionCaseRef cenv ucref - let typR = ConvType cenv (mkAppTy ucref.TyconRef tyargs) + let typR = ConvType cenv (mkWoNullAppTy ucref.TyconRef tyargs) let projR = FSharpField(cenv, ucref, n) E.UnionCaseSet(ConvExpr cenv env e1, typR, mkR, projR, ConvExpr cenv env e2) @@ -665,13 +665,13 @@ module FSharpExprConvert = | TOp.ValFieldGet rfref, tyargs, [] -> let projR = ConvRecdFieldRef cenv rfref - let typR = ConvType cenv (mkAppTy rfref.TyconRef tyargs) + let typR = ConvType cenv (mkWoNullAppTy rfref.TyconRef tyargs) E.FSharpFieldGet(None, typR, projR) | TOp.ValFieldGet rfref, tyargs, [obj] -> let objR = ConvLValueExpr cenv env obj let projR = ConvRecdFieldRef cenv rfref - let typR = ConvType cenv (mkAppTy rfref.TyconRef tyargs) + let typR = ConvType cenv (mkWoNullAppTy rfref.TyconRef tyargs) E.FSharpFieldGet(Some objR, typR, projR) | TOp.TupleFieldGet (tupInfo, n), tyargs, [e] -> @@ -775,7 +775,7 @@ module FSharpExprConvert = let argTy2 = tyOfExpr g arg2 let resTy = match getMeasureOfType g argTy1, getMeasureOfType g argTy2 with - | Some (tcref, ms1), Some (_tcref2, ms2) -> mkAppTy tcref [TType_measure (Measure.Prod(ms1, if isMul then ms2 else Measure.Inv ms2))] + | Some (tcref, ms1), Some (_tcref2, ms2) -> mkWoNullAppTy tcref [TType_measure (Measure.Prod(ms1, if isMul then ms2 else Measure.Inv ms2))] | Some _, None -> argTy1 | None, Some _ -> argTy2 | None, None -> argTy1 @@ -805,18 +805,18 @@ module FSharpExprConvert = E.ILAsm(sprintf "%+A" instrs, ConvTypes cenv tyargs, ConvExprs cenv env args) | TOp.ExnConstr tcref, tyargs, args -> - E.NewRecord(ConvType cenv (mkAppTy tcref tyargs), ConvExprs cenv env args) + E.NewRecord(ConvType cenv (mkWoNullAppTy tcref tyargs), ConvExprs cenv env args) | TOp.ValFieldSet rfref, _tinst, [obj;arg] -> let objR = ConvLValueExpr cenv env obj let argR = ConvExpr cenv env arg - let typR = ConvType cenv (mkAppTy rfref.TyconRef tyargs) + let typR = ConvType cenv (mkWoNullAppTy rfref.TyconRef tyargs) let projR = ConvRecdFieldRef cenv rfref E.FSharpFieldSet(Some objR, typR, projR, argR) | TOp.ValFieldSet rfref, _tinst, [arg] -> let argR = ConvExpr cenv env arg - let typR = ConvType cenv (mkAppTy rfref.TyconRef tyargs) + let typR = ConvType cenv (mkWoNullAppTy rfref.TyconRef tyargs) let projR = ConvRecdFieldRef cenv rfref E.FSharpFieldSet(None, typR, projR, argR) @@ -824,16 +824,16 @@ module FSharpExprConvert = let exnc = stripExnEqns tcref let fspec = exnc.TrueInstanceFieldsAsList[i] let fref = mkRecdFieldRef tcref fspec.LogicalName - let typR = ConvType cenv (mkAppTy tcref tyargs) - let objR = ConvExpr cenv env (mkCoerceExpr (obj, mkAppTy tcref [], m, g.exn_ty)) + let typR = ConvType cenv (mkWoNullAppTy tcref tyargs) + let objR = ConvExpr cenv env (mkCoerceExpr (obj, mkWoNullAppTy tcref [], m, g.exn_ty)) E.FSharpFieldGet(Some objR, typR, ConvRecdFieldRef cenv fref) | TOp.ExnFieldSet (tcref, i), [], [obj;e2] -> let exnc = stripExnEqns tcref let fspec = exnc.TrueInstanceFieldsAsList[i] let fref = mkRecdFieldRef tcref fspec.LogicalName - let typR = ConvType cenv (mkAppTy tcref tyargs) - let objR = ConvExpr cenv env (mkCoerceExpr (obj, mkAppTy tcref [], m, g.exn_ty)) + let typR = ConvType cenv (mkWoNullAppTy tcref tyargs) + let objR = ConvExpr cenv env (mkCoerceExpr (obj, mkWoNullAppTy tcref [], m, g.exn_ty)) E.FSharpFieldSet(Some objR, typR, ConvRecdFieldRef cenv fref, ConvExpr cenv env e2) | TOp.Coerce, [tgtTy;srcTy], [x] -> @@ -896,7 +896,7 @@ module FSharpExprConvert = | TOp.UnionCaseProof _, _, [e] -> ConvExprPrim cenv env e // Note: we erase the union case proof conversions when converting to quotations | TOp.UnionCaseTagGet tycr, tyargs, [arg1] -> - let typR = ConvType cenv (mkAppTy tycr tyargs) + let typR = ConvType cenv (mkWoNullAppTy tycr tyargs) E.UnionCaseTag(ConvExpr cenv env arg1, typR) | TOp.TraitCall traitInfo, _, _ -> @@ -1019,7 +1019,7 @@ module FSharpExprConvert = | [v] -> makeFSCall isMember v | [] -> - let typR = ConvType cenv (mkAppTy tcref enclTypeArgs) + let typR = ConvType cenv (mkWoNullAppTy tcref enclTypeArgs) if enclosingEntity.IsModuleOrNamespace then let findModuleMemberByName = enclosingEntity.ModuleOrNamespaceType.AllValsAndMembers @@ -1295,7 +1295,7 @@ module FSharpExprConvert = | DecisionTreeTest.UnionCase (ucref, tyargs) -> let objR = ConvExpr cenv env inpExpr let ucR = ConvUnionCaseRef cenv ucref - let utypR = ConvType cenv (mkAppTy ucref.TyconRef tyargs) + let utypR = ConvType cenv (mkWoNullAppTy ucref.TyconRef tyargs) E.IfThenElse (E.UnionCaseTest (objR, utypR, ucR) |> Mk cenv m g.bool_ty, ConvDecisionTree cenv env dtreeRetTy dtree m, acc) | DecisionTreeTest.Const (Const.Bool true) -> let e1R = ConvExpr cenv env inpExpr diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs index f57e00d0158..da6977c1dd4 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.fs @@ -863,7 +863,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, KnownWithoutNull) // TODO NULLNESS - check various callers +let mkWoNullAppTy tcref tyargs = TType_app(tcref, tyargs, KnownWithoutNull) let mkProvenUnionCaseTy ucref tyargs = TType_ucase(ucref, tyargs) @@ -923,7 +923,7 @@ let convertToTypeWithMetadataIfPossible g ty = mkOuterCompiledTupleTy g (evalTupInfoIsStruct tupInfo) tupElemTys elif isFunTy g ty then let a,b = destFunTy g ty - mkAppTy g.fastFunc_tcr [a; b] + mkWoNullAppTy g.fastFunc_tcr [a; b] else ty //--------------------------------------------------------------------------- @@ -6636,7 +6636,7 @@ let rec tyOfExpr g expr = | TOp.ILCall (_, _, _, _, _, _, _, _, _, _, retTypes) | TOp.ILAsm (_, retTypes) -> (match retTypes with [h] -> h | _ -> g.unit_ty) | TOp.UnionCase uc -> actualResultTyOfUnionCase tinst uc | TOp.UnionCaseProof uc -> mkProvenUnionCaseTy uc tinst - | TOp.Recd (_, tcref) -> mkAppTy tcref tinst + | TOp.Recd (_, tcref) -> mkWoNullAppTy tcref tinst | TOp.ExnConstr _ -> g.exn_ty | TOp.Bytes _ -> mkByteArrayTy g | TOp.UInt16s _ -> mkArrayType g g.uint16_ty @@ -7628,7 +7628,7 @@ let permuteExprList (sigma: int[]) (exprs: Expr list) (ty: TType list) (names: s /// We still need to sort by index. let mkRecordExpr g (lnk, tcref, tinst, unsortedRecdFields: RecdFieldRef list, unsortedFieldExprs, m) = // Remove any abbreviations - let tcref, tinst = destAppTy g (mkAppTy tcref tinst) + let tcref, tinst = destAppTy g (mkWoNullAppTy tcref tinst) let sortedRecdFields = unsortedRecdFields |> List.indexed |> Array.ofList |> Array.sortBy (fun (_, r) -> r.Index) let sigma = Array.create sortedRecdFields.Length -1 @@ -7913,9 +7913,9 @@ let TryEliminateDesugaredConstants g m c = | _ -> None -let mkSeqTy (g: TcGlobals) ty = mkAppTy g.seq_tcr [ty] +let mkSeqTy (g: TcGlobals) ty = mkWoNullAppTy g.seq_tcr [ty] -let mkIEnumeratorTy (g: TcGlobals) ty = mkAppTy g.tcref_System_Collections_Generic_IEnumerator [ty] +let mkIEnumeratorTy (g: TcGlobals) ty = mkWoNullAppTy g.tcref_System_Collections_Generic_IEnumerator [ty] let mkCallSeqCollect g m alphaTy betaTy arg1 arg2 = let enumty2 = try rangeOfFunTy g (tyOfExpr g arg1) with _ -> (* defensive programming *) (mkSeqTy g betaTy) @@ -9392,7 +9392,7 @@ let mkChoiceTy (g: TcGlobals) m tinst = match List.length tinst with | 0 -> g.unit_ty | 1 -> List.head tinst - | length -> mkAppTy (mkChoiceTyconRef g m length) tinst + | length -> mkWoNullAppTy (mkChoiceTyconRef g m length) tinst let mkChoiceCaseRef g m n i = mkUnionCaseRef (mkChoiceTyconRef g m n) ("Choice"+string (i+1)+"Of"+string n) diff --git a/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi index 4b617dc1965..f5860214113 100755 --- a/src/Compiler/TypedTree/TypedTreeOps.fsi +++ b/src/Compiler/TypedTree/TypedTreeOps.fsi @@ -686,7 +686,7 @@ val tryAnyParTyOption: TcGlobals -> TType -> Typar option val isMeasureTy: TcGlobals -> TType -> bool -val mkAppTy: TyconRef -> TypeInst -> TType +val mkWoNullAppTy: TyconRef -> TypeInst -> TType val mkProvenUnionCaseTy: UnionCaseRef -> TypeInst -> TType From 1429960f9891792e860fe6bc931ddbae97530c9b Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 14 Mar 2024 13:42:47 +0100 Subject: [PATCH 02/11] mkFunTyWithNullness --- src/Compiler/TypedTree/TcGlobals.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs index 895a821fbb6..9f5f1d91239 100644 --- a/src/Compiler/TypedTree/TcGlobals.fs +++ b/src/Compiler/TypedTree/TcGlobals.fs @@ -463,6 +463,7 @@ type TcGlobals( let mkByrefTy ty = TType_app(v_byref_tcr, [ty], v_knownWithoutNull) let mkNativePtrTy ty = TType_app(v_nativeptr_tcr, [ty], v_knownWithoutNull) let mkFunTy d r = TType_fun (d, r, v_knownWithoutNull) + let mkFunTyWithNullness d r nullness = TType_fun (d, r, nullness) let (-->) d r = mkFunTy d r let mkIteratedFunTy dl r = List.foldBack mkFunTy dl r let mkSmallRefTupledTy l = match l with [] -> v_unit_ty | [h] -> h | tys -> mkRawRefTupleTy tys @@ -991,8 +992,7 @@ type TcGlobals( let decompileTyconEntries = [| - // TODO: nullness here - "FSharpFunc`2" , v_fastFunc_tcr , (fun tinst _nullness -> mkFunTy (List.item 0 tinst) (List.item 1 tinst)) + "FSharpFunc`2" , v_fastFunc_tcr , (fun tinst -> mkFunTyWithNullness (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 From 664416c4e5474ce376e9fb09b0538621af36c665 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 18 Mar 2024 16:17:51 +0100 Subject: [PATCH 03/11] adding failing tests for fsharp types --- .../Language/NullableReferenceTypesTests.fs | 106 +++++++++++++++++- 1 file changed, 104 insertions(+), 2 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs index 9dca34495c5..c0d0cfd158d 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs @@ -9,7 +9,7 @@ let typeCheckWithStrictNullness cu = |> withCheckNulls |> withWarnOn 3261 |> withOptions ["--warnaserror+"] - |> compile + |> typecheck [] @@ -183,4 +183,106 @@ let myFunction (input1 : string | null) (input2 : string | null): (string*string |> asLibrary |> typeCheckWithStrictNullness |> shouldFail - |> withErrorCode 3261 \ No newline at end of file + |> withErrorCode 3261 + +[] +let ``WithNull used on anon type`` () = + FSharp """module MyLibrary + +let strictFunc(arg: 'x when 'x : not null) = arg.ToString() +let looseFunc(arg: _ | null) = arg + +strictFunc({|ZZ=15;YZ="a"|}) |> ignore +looseFunc({|ZZ=15;YZ="a"|}) |> ignore + +let maybeAnon : _ | null = {|Hello="there"|} +let maybeAnon2 : _ | null = null + +strictFunc(maybeAnon) |> ignore +looseFunc(maybeAnon) |> ignore + +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed + + +[] +let ``WithNull on a DU`` () = + FSharp """module MyLibrary +type MyDu = A | B + + +let strictFunc(arg: 'x when 'x : not null) = + printfn "%A" arg + arg + +let looseFunc(arg: _ | null) = arg + +strictFunc(A) |> ignore +looseFunc(A) |> ignore + +let maybeDu : _ | null = MyDu.A +let maybeDu2 : _ | null = null + +strictFunc(maybeDu) |> ignore +strictFunc(maybeDu2) |> ignore + +looseFunc(maybeDu2) |> ignore +looseFunc(maybeDu2) |> ignore + +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed + +[] +let ``Nullnesss support for F# types`` () = + FSharp """module MyLibrary +type MyDu = A | B +type MyRecord = {X:int;Y:string} + +let strictFunc(arg: 'x when 'x : not null) = + printfn "%A" arg + arg + +let looseFunc(arg: _ | null) = arg + +strictFunc(A) |> ignore +strictFunc({X=1;Y="a"}) |> ignore +strictFunc({|ZZ=15;YZ="a"|}) |> ignore +strictFunc((1,2,3)) |> ignore + +looseFunc(A) |> ignore +looseFunc({X=1;Y="a"}) |> ignore +looseFunc({|ZZ=15;YZ="a"|}) |> ignore +looseFunc((1,2,3)) |> ignore + +strictFunc(null) |> ignore +looseFunc(null) |> ignore + +let maybeDu : _ | null = MyDu.A +let maybeRecd : MyRecord | null = {X=1;Y="a"} +let maybeAnon : _ | null = {|Hello="there"|} +let maybeTuple : (int*int) | null = null + +strictFunc(maybeDu) |> ignore +strictFunc(maybeRecd) |> ignore +strictFunc(maybeAnon) |> ignore +strictFunc(maybeTuple) |> ignore + +looseFunc(maybeDu) |> ignore +looseFunc(maybeRecd) |> ignore +looseFunc(maybeAnon) |> ignore +looseFunc(maybeTuple) |> ignore + +type Maybe<'T> = 'T | null +let maybeTuple2 : Maybe = null +strictFunc(maybeTuple2) |> ignore +looseFunc(maybeTuple2) |> ignore + + +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed \ No newline at end of file From 5247050920354f46f203422068170f4807d85bee Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Wed, 20 Mar 2024 15:11:07 +0100 Subject: [PATCH 04/11] delayed checks of post-infered values for nullness-carrying capabilities --- src/Compiler/Checking/CheckExpressions.fs | 5 ++++ src/Compiler/Checking/ConstraintSolver.fs | 18 +++++++++++++ src/Compiler/Checking/ConstraintSolver.fsi | 2 ++ 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 +++++++++++++++++++ .../Language/NullableReferenceTypesTests.fs | 23 ++++++----------- 17 files changed, 358 insertions(+), 15 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 6a2fa281af4..f5f650af5ad 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -1041,6 +1041,11 @@ let TcAddNullnessToType (warn: bool) (cenv: cenv) (env: TcEnv) nullness innerTyC if not g.compilingFSharpCore || not (isTyparTy g innerTyC) then AddCxTypeDefnNotSupportsNull env.DisplayEnv cenv.css m NoTrace innerTyC + if not g.compilingFSharpCore && isTyparTy g innerTyC then + // A typar might be later infered into a type not supporting `| null|, like tuple or anon. + // Repeat the check in post inference + AddCxTypeCanCarryNullnessInfo env.DisplayEnv cenv.css m innerTyC nullness + innerTyCWithNull else diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index 72530a44de4..1e3dde449f8 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -2614,6 +2614,18 @@ and SolveNullnessNotSupportsNull (csenv: ConstraintSolverEnv) ndeep m2 (trace: O return! WarnD(ConstraintSolverNullnessWarning(FSComp.SR.csTypeHasNullAsExtraValue(NicePrint.minimalStringOfType denv ty), m, m2)) } +and SolveTypeCanCarryNullness (csenv: ConstraintSolverEnv) ty nullness = + trackErrors { + let g = csenv.g + let m = csenv.m + let strippedTy = stripTyEqnsA g true ty + match tryAddNullnessToTy nullness strippedTy with + | Some _ -> () + | None -> + let tyString = NicePrint.minimalStringOfType csenv.DisplayEnv strippedTy + return! ErrorD(Error(FSComp.SR.tcTypeDoesNotHaveAnyNull(tyString), m)) + } + and SolveTypeSupportsComparison (csenv: ConstraintSolverEnv) ndeep m2 trace ty = let g = csenv.g let m = csenv.m @@ -3876,6 +3888,12 @@ let AddCxTypeUseSupportsNull denv css m trace ty = (fun res -> ErrorD (ErrorFromAddingConstraint(denv, res, m))) |> RaiseOperationResult +let AddCxTypeCanCarryNullnessInfo denv css m ty nullness = + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m denv + let canCarryNullnessCheck() = SolveTypeCanCarryNullness csenv ty nullness |> RaiseOperationResult + csenv.SolverState.PushPostInferenceCheck (preDefaults=false, check = canCarryNullnessCheck) + + let AddCxTypeMustSupportComparison 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 371fa31e598..c8169051be4 100644 --- a/src/Compiler/Checking/ConstraintSolver.fsi +++ b/src/Compiler/Checking/ConstraintSolver.fsi @@ -267,6 +267,8 @@ val AddCxTypeDefnNotSupportsNull: DisplayEnv -> ConstraintSolverState -> range - val AddCxTypeUseSupportsNull: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit +val AddCxTypeCanCarryNullnessInfo: DisplayEnv -> ConstraintSolverState -> range -> TType -> Nullness -> unit + val AddCxTypeMustSupportComparison: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit val AddCxTypeMustSupportEquality: DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> unit diff --git a/src/Compiler/xlf/FSStrings.cs.xlf b/src/Compiler/xlf/FSStrings.cs.xlf index 6a3e83c532a..9d0a6111f0c 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. + + The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} @@ -37,6 +57,11 @@ Očekává se statický člen. + + 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 8777c4ab388..ca238a47c3e 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. + + The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} @@ -37,6 +57,11 @@ Ein statischer Member wird erwartet. + + 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 6484fb847fb..5c95db8c1ce 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. + + The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} @@ -37,6 +57,11 @@ Se espera un miembro estático. + + 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 3b15aaca563..56b8b1ea919 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. + + The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} @@ -37,6 +57,11 @@ Un membre statique est attendu. + + 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 304025244e0..1b530f39425 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. + + The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} @@ -37,6 +57,11 @@ È previsto un membro statico. + + 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 31ba40fcb3d..0f89ac43fa5 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. + + The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} @@ -37,6 +57,11 @@ 静的メンバーが必要です。 + + 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 f0bbe7c8aae..e1e5a08529f 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. + + The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} @@ -37,6 +57,11 @@ 정적 멤버가 필요합니다. + + 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 3020002ce7c..f91277e1675 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. + + The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} @@ -37,6 +57,11 @@ Oczekiwano statycznego elementu członkowskiego. + + 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 b5647b8d0eb..71699f1201d 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. + + The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} @@ -37,6 +57,11 @@ O membro estático é esperado. + + 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 b47eb92bdc3..f62266849f4 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. + + The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} @@ -37,6 +57,11 @@ Ожидается статический элемент. + + 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 2fc08de7f13..418144052a7 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. + + The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} @@ -37,6 +57,11 @@ Statik üye bekleniyor. + + 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 f81bb2b61c7..0707623646c 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. + + The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} @@ -37,6 +57,11 @@ 应为静态成员。 + + 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 d0de30dc7ff..a99363aade0 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. + + The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} @@ -37,6 +57,11 @@ 必須是靜態成員。 + + symbol '|' (directly before 'null') + symbol '|' (directly before 'null') + + symbol '..^' 符號 '..^' diff --git a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs index c0d0cfd158d..1c2c8f19d5e 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs @@ -189,22 +189,13 @@ let myFunction (input1 : string | null) (input2 : string | null): (string*string let ``WithNull used on anon type`` () = FSharp """module MyLibrary -let strictFunc(arg: 'x when 'x : not null) = arg.ToString() -let looseFunc(arg: _ | null) = arg - -strictFunc({|ZZ=15;YZ="a"|}) |> ignore -looseFunc({|ZZ=15;YZ="a"|}) |> ignore - -let maybeAnon : _ | null = {|Hello="there"|} -let maybeAnon2 : _ | null = null - -strictFunc(maybeAnon) |> ignore -looseFunc(maybeAnon) |> ignore - +//let maybeAnon : _ | null = {|Hello="there"|} +let maybeAnon2 : {|Hello:string|} | null = null """ |> asLibrary |> typeCheckWithStrictNullness - |> shouldSucceed + |> shouldFail + |> withDiagnostics [] [] @@ -234,7 +225,8 @@ looseFunc(maybeDu2) |> ignore """ |> asLibrary |> typeCheckWithStrictNullness - |> shouldSucceed + |> shouldFail + |> withDiagnostics [] [] let ``Nullnesss support for F# types`` () = @@ -285,4 +277,5 @@ looseFunc(maybeTuple2) |> ignore """ |> asLibrary |> typeCheckWithStrictNullness - |> shouldSucceed \ No newline at end of file + |> shouldFail + |> withDiagnostics [] \ No newline at end of file From e4c0bfde7713c0cc24357f32aee033ad83ebf6b0 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Wed, 20 Mar 2024 19:31:23 +0100 Subject: [PATCH 05/11] more tests --- .../Language/NullableReferenceTypesTests.fs | 119 +++++++++++++++++- 1 file changed, 117 insertions(+), 2 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs index 1c2c8f19d5e..2aed3cd52e7 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs @@ -189,7 +189,7 @@ let myFunction (input1 : string | null) (input2 : string | null): (string*string let ``WithNull used on anon type`` () = FSharp """module MyLibrary -//let maybeAnon : _ | null = {|Hello="there"|} +let maybeAnon : _ | null = {|Hello="there"|} let maybeAnon2 : {|Hello:string|} | null = null """ |> asLibrary @@ -278,4 +278,119 @@ looseFunc(maybeTuple2) |> ignore |> asLibrary |> typeCheckWithStrictNullness |> shouldFail - |> withDiagnostics [] \ No newline at end of file + |> withDiagnostics [] + + +[] +let ``Static member on Record with null arg`` () = + FSharp """module MyLibrary +type MyRecord = {X:string;Y:int} + with static member Create(x:string) = {X=x;Y = 42} +let thisWorks = MyRecord.Create("xx") +let thisShouldWarn = MyRecord.Create(null) +let maybeNull : string | null = "abc" +let thisShouldAlsoWarn = MyRecord.Create(maybeNull) +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withDiagnostics + [Error 3261, Line 7, Col 38, Line 7, Col 42, "Nullness warning: The type 'string' does not support 'null'." + Error 3261, Line 9, Col 42, Line 9, Col 51, "Nullness warning: The types 'string' and 'string | null' do not have equivalent nullability."] + + +[] +let ``Option ofObj should remove nullness when used in a function`` () = + FSharp """module MyLibrary +let processOpt2 (s: string | null) : string option = Option.ofObj s""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed + +[] +let ``Option ofObj should remove nullness when piping`` () = + FSharp """module MyLibrary +let processOpt (s: string | null) : string option = + let stringOpt = Option.ofObj s + stringOpt +let processOpt3 (s: string | null) : string option = s |> Option.ofObj +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed + +[] +let ``Option ofObj called in a useless way raises warning`` () = + FSharp """module MyLibrary +let processOpt1 (s: string) = Option.ofObj s +let processOpt2 (s: string) : option = + Option.ofObj s +let processOpt3 (s: string) : string option = + let sOpt = Option.ofObj s + sOpt +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withDiagnostics + [ Error 3262, Line 3, Col 44, Line 3, Col 45, "Value known to be without null passed to a function meant for nullables: You can create 'Some value' directly instead of 'ofObj', or consider not using an option for this value." + Error 3262, Line 5, Col 18, Line 5, Col 19, "Value known to be without null passed to a function meant for nullables: You can create 'Some value' directly instead of 'ofObj', or consider not using an option for this value." + Error 3262, Line 7, Col 29, Line 7, Col 30, "Value known to be without null passed to a function meant for nullables: You can create 'Some value' directly instead of 'ofObj', or consider not using an option for this value."] + + +[] +let ``Option ofObj called on a string literal`` () = + FSharp """module MyLibrary +let whatIsThis = Option.ofObj "abc123" +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withErrorCodes [3262] + +[] +let ``Useless null pattern match`` () = + FSharp """module MyLibrary +let clearlyNotNull = "42" +let mappedVal = + match clearlyNotNull with + | null -> 42 + | _ -> 43 +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withDiagnostics [Error 3261, Line 6, Col 7, Line 6, Col 11, "Nullness warning: The type 'string' does not support 'null'."] + +[] +let ``Useless usage of nonNull utility from fscore`` () = + FSharp """module MyLibrary +let clearlyNotNull = "42" +let mappedVal = nonNull clearlyNotNull +let maybeNull : string | null = null +let mappedMaybe = nonNull maybeNull +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withDiagnostics [Error 3262, Line 4, Col 25, Line 4, Col 39, "Value known to be without null passed to a function meant for nullables: You can remove this `nonNull` assertion."] + +[] +let ``Useless usage of null active patterns from fscore`` () = + FSharp """module MyLibrary +let clearlyNotNull = "42" +let mapped1 = + match clearlyNotNull with + | NonNullQuick safe -> safe +let mapped2 = + match clearlyNotNull with + |Null -> 0 + |NonNull _ -> 1 +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withDiagnostics + [ Error 3262, Line 6, Col 7, Line 6, Col 24, "Value known to be without null passed to a function meant for nullables: You can remove this |NonNullQuick| pattern usage." + Error 3262, Line 10, Col 6, Line 10, Col 10, "Value known to be without null passed to a function meant for nullables: You can remove this |Null|NonNull| pattern usage." + Error 3262, Line 11, Col 6, Line 11, Col 15, "Value known to be without null passed to a function meant for nullables: You can remove this |Null|NonNull| pattern usage."] \ No newline at end of file From 4827b98791784a0b0c13ecbb634db38a027a507f Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Fri, 22 Mar 2024 14:42:54 +0100 Subject: [PATCH 06/11] fix xliffs --- src/Compiler/xlf/FSStrings.cs.xlf | 5 ----- src/Compiler/xlf/FSStrings.de.xlf | 7 +------ 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 ----- 13 files changed, 1 insertion(+), 66 deletions(-) diff --git a/src/Compiler/xlf/FSStrings.cs.xlf b/src/Compiler/xlf/FSStrings.cs.xlf index b00f06f2a6c..bdaa68e4447 100644 --- a/src/Compiler/xlf/FSStrings.cs.xlf +++ b/src/Compiler/xlf/FSStrings.cs.xlf @@ -32,11 +32,6 @@ Nullness warning: The types '{0}' and '{1}' do not have compatible nullability. - - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {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 diff --git a/src/Compiler/xlf/FSStrings.de.xlf b/src/Compiler/xlf/FSStrings.de.xlf index 382ceeba77e..2b23796249e 100644 --- a/src/Compiler/xlf/FSStrings.de.xlf +++ b/src/Compiler/xlf/FSStrings.de.xlf @@ -10,7 +10,7 @@ The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} - + Nullness warning: {0}. @@ -32,11 +32,6 @@ Nullness warning: The types '{0}' and '{1}' do not have compatible nullability. - - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {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. diff --git a/src/Compiler/xlf/FSStrings.es.xlf b/src/Compiler/xlf/FSStrings.es.xlf index 0de077b722c..c959faa16a0 100644 --- a/src/Compiler/xlf/FSStrings.es.xlf +++ b/src/Compiler/xlf/FSStrings.es.xlf @@ -32,11 +32,6 @@ Nullness warning: The types '{0}' and '{1}' do not have compatible nullability. - - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {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 diff --git a/src/Compiler/xlf/FSStrings.fr.xlf b/src/Compiler/xlf/FSStrings.fr.xlf index fe9fb073e71..2291e1b8663 100644 --- a/src/Compiler/xlf/FSStrings.fr.xlf +++ b/src/Compiler/xlf/FSStrings.fr.xlf @@ -32,11 +32,6 @@ Nullness warning: The types '{0}' and '{1}' do not have compatible nullability. - - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {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 diff --git a/src/Compiler/xlf/FSStrings.it.xlf b/src/Compiler/xlf/FSStrings.it.xlf index 4f2ad100fbb..4039607d97d 100644 --- a/src/Compiler/xlf/FSStrings.it.xlf +++ b/src/Compiler/xlf/FSStrings.it.xlf @@ -32,11 +32,6 @@ Nullness warning: The types '{0}' and '{1}' do not have compatible nullability. - - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {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 diff --git a/src/Compiler/xlf/FSStrings.ja.xlf b/src/Compiler/xlf/FSStrings.ja.xlf index 381fc69aa55..639885ed89e 100644 --- a/src/Compiler/xlf/FSStrings.ja.xlf +++ b/src/Compiler/xlf/FSStrings.ja.xlf @@ -32,11 +32,6 @@ Nullness warning: The types '{0}' and '{1}' do not have compatible nullability. - - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {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 diff --git a/src/Compiler/xlf/FSStrings.ko.xlf b/src/Compiler/xlf/FSStrings.ko.xlf index 0b8d143fa17..f449634f49f 100644 --- a/src/Compiler/xlf/FSStrings.ko.xlf +++ b/src/Compiler/xlf/FSStrings.ko.xlf @@ -32,11 +32,6 @@ Nullness warning: The types '{0}' and '{1}' do not have compatible nullability. - - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {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 diff --git a/src/Compiler/xlf/FSStrings.pl.xlf b/src/Compiler/xlf/FSStrings.pl.xlf index bf2362a2e1b..ed9cfaa49b9 100644 --- a/src/Compiler/xlf/FSStrings.pl.xlf +++ b/src/Compiler/xlf/FSStrings.pl.xlf @@ -32,11 +32,6 @@ Nullness warning: The types '{0}' and '{1}' do not have compatible nullability. - - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {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 diff --git a/src/Compiler/xlf/FSStrings.pt-BR.xlf b/src/Compiler/xlf/FSStrings.pt-BR.xlf index a52ded8a22d..0a9c5127b6f 100644 --- a/src/Compiler/xlf/FSStrings.pt-BR.xlf +++ b/src/Compiler/xlf/FSStrings.pt-BR.xlf @@ -32,11 +32,6 @@ Nullness warning: The types '{0}' and '{1}' do not have compatible nullability. - - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {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 diff --git a/src/Compiler/xlf/FSStrings.ru.xlf b/src/Compiler/xlf/FSStrings.ru.xlf index c12ee893b2c..2d0d0fe75c7 100644 --- a/src/Compiler/xlf/FSStrings.ru.xlf +++ b/src/Compiler/xlf/FSStrings.ru.xlf @@ -32,11 +32,6 @@ Nullness warning: The types '{0}' and '{1}' do not have compatible nullability. - - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {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 diff --git a/src/Compiler/xlf/FSStrings.tr.xlf b/src/Compiler/xlf/FSStrings.tr.xlf index 464a295eb95..6044f1c9827 100644 --- a/src/Compiler/xlf/FSStrings.tr.xlf +++ b/src/Compiler/xlf/FSStrings.tr.xlf @@ -32,11 +32,6 @@ Nullness warning: The types '{0}' and '{1}' do not have compatible nullability. - - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {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 diff --git a/src/Compiler/xlf/FSStrings.zh-Hans.xlf b/src/Compiler/xlf/FSStrings.zh-Hans.xlf index 547100feaef..c237edfd050 100644 --- a/src/Compiler/xlf/FSStrings.zh-Hans.xlf +++ b/src/Compiler/xlf/FSStrings.zh-Hans.xlf @@ -32,11 +32,6 @@ Nullness warning: The types '{0}' and '{1}' do not have compatible nullability. - - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {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 diff --git a/src/Compiler/xlf/FSStrings.zh-Hant.xlf b/src/Compiler/xlf/FSStrings.zh-Hant.xlf index 3da2c9103aa..9533bfe8c0d 100644 --- a/src/Compiler/xlf/FSStrings.zh-Hant.xlf +++ b/src/Compiler/xlf/FSStrings.zh-Hant.xlf @@ -32,11 +32,6 @@ Nullness warning: The types '{0}' and '{1}' do not have compatible nullability. - - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {3} - The {0} definitions for type '{1}' in the signature and implementation are not compatible because the abbreviations differ:\n {2}\nversus\n {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} From cc102b4f730a01353a391975a19ca887e23e0804 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 25 Mar 2024 15:05:03 +0100 Subject: [PATCH 07/11] Regression on passing null literal - to be fixed --- .../Language/NullableReferenceTypesTests.fs | 47 +++++++++++++++++-- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs index 2aed3cd52e7..407258d9994 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs @@ -195,12 +195,15 @@ let maybeAnon2 : {|Hello:string|} | null = null |> asLibrary |> typeCheckWithStrictNullness |> shouldFail - |> withDiagnostics [] + |> withDiagnostics + [ Error 3260, Line 4, Col 18, Line 4, Col 41, "The type '{| Hello: string |}' does not support a nullness qualitification." + Error 3261, Line 4, Col 44, Line 4, Col 48, "Nullness warning: The type '{| Hello: string |}' does not support 'null'."] [] let ``WithNull on a DU`` () = FSharp """module MyLibrary + type MyDu = A | B @@ -226,7 +229,30 @@ looseFunc(maybeDu2) |> ignore |> asLibrary |> typeCheckWithStrictNullness |> shouldFail - |> withDiagnostics [] + |> withDiagnostics [ + Error 3261, Line 18, Col 12, Line 18, Col 19, "Nullness warning: The type 'MyDu | null' supports 'null' but a non-null type is expected." + Error 3261, Line 19, Col 12, Line 19, Col 20, "Nullness warning: The type ''a | null' supports 'null' but a non-null type is expected."] + +[] +let ``Regression strict func`` () = + FSharp """module MyLibrary +let strictFunc(arg: 'x when 'x : not null) = + printfn "%A" arg + arg + +strictFunc({|Anon=5|}) |> ignore +strictFunc("hi") |> ignore +strictFunc(null) |> ignore +strictFunc(null:(string|null)) |> ignore +strictFunc(null:obj) |> ignore + + """ + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withDiagnostics + [ ] + [] let ``Nullnesss support for F# types`` () = @@ -278,14 +304,20 @@ looseFunc(maybeTuple2) |> ignore |> asLibrary |> typeCheckWithStrictNullness |> shouldFail - |> withDiagnostics [] - - + |> withDiagnostics + [ Error 3260, Line 27, Col 18, Line 27, Col 34, "The type '(int * int)' does not support a nullness qualitification." + Error 3261, Line 27, Col 37, Line 27, Col 41, "Nullness warning: The type '(int * int)' does not support 'null'." + Error 3261, Line 29, Col 12, Line 29, Col 19, "Nullness warning: The type 'MyDu | null' supports 'null' but a non-null type is expected." + Error 3261, Line 30, Col 12, Line 30, Col 21, "Nullness warning: The type 'MyRecord | null' supports 'null' but a non-null type is expected." + Error 3261, Line 40, Col 36, Line 40, Col 40, "Nullness warning: The type 'Maybe' does not support 'null'."] + [] let ``Static member on Record with null arg`` () = FSharp """module MyLibrary + type MyRecord = {X:string;Y:int} with static member Create(x:string) = {X=x;Y = 42} + let thisWorks = MyRecord.Create("xx") let thisShouldWarn = MyRecord.Create(null) let maybeNull : string | null = "abc" @@ -322,6 +354,7 @@ let processOpt3 (s: string | null) : string option = s |> Option.ofObj [] let ``Option ofObj called in a useless way raises warning`` () = FSharp """module MyLibrary + let processOpt1 (s: string) = Option.ofObj s let processOpt2 (s: string) : option = Option.ofObj s @@ -351,6 +384,7 @@ let whatIsThis = Option.ofObj "abc123" [] let ``Useless null pattern match`` () = FSharp """module MyLibrary + let clearlyNotNull = "42" let mappedVal = match clearlyNotNull with @@ -365,6 +399,7 @@ let mappedVal = [] let ``Useless usage of nonNull utility from fscore`` () = FSharp """module MyLibrary + let clearlyNotNull = "42" let mappedVal = nonNull clearlyNotNull let maybeNull : string | null = null @@ -378,10 +413,12 @@ let mappedMaybe = nonNull maybeNull [] let ``Useless usage of null active patterns from fscore`` () = FSharp """module MyLibrary + let clearlyNotNull = "42" let mapped1 = match clearlyNotNull with | NonNullQuick safe -> safe + let mapped2 = match clearlyNotNull with |Null -> 0 From bd62198229fa8d9941342e7c89d0ffa2d12aa29a Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 26 Mar 2024 10:38:03 +0100 Subject: [PATCH 08/11] regression with obj - captured as a test --- .../Language/NullableReferenceTypesTests.fs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs index 407258d9994..2d2626aabbc 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs @@ -236,9 +236,7 @@ looseFunc(maybeDu2) |> ignore [] let ``Regression strict func`` () = FSharp """module MyLibrary -let strictFunc(arg: 'x when 'x : not null) = - printfn "%A" arg - arg +let strictFunc(arg: 'x when 'x : not null) = printfn "%s" (arg.ToString()) strictFunc({|Anon=5|}) |> ignore strictFunc("hi") |> ignore @@ -251,7 +249,7 @@ strictFunc(null:obj) |> ignore |> typeCheckWithStrictNullness |> shouldFail |> withDiagnostics - [ ] + [ Error 3261, Line 7, Col 12, Line 7, Col 30, "Nullness warning: The type 'string | null' supports 'null' but a non-null type is expected." ] [] From f0b4c38e2d3b0bb4a65c7567cb2e568c37a4e8db Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 26 Mar 2024 10:44:58 +0100 Subject: [PATCH 09/11] autowiden tests change from preview to 8 --- .../Miscellaneous/MigratedCoreTests.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Miscellaneous/MigratedCoreTests.fs b/tests/FSharp.Compiler.ComponentTests/Miscellaneous/MigratedCoreTests.fs index e92ef88592c..1b524fe445a 100644 --- a/tests/FSharp.Compiler.ComponentTests/Miscellaneous/MigratedCoreTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Miscellaneous/MigratedCoreTests.fs @@ -78,11 +78,11 @@ let ``auto-widen-minimal``() = [] let ``auto-widen-version-preview-warns-on``() = - singleVersionedNegTestAux "core/auto-widen/preview" ["--warnon:3388";"--warnon:3389";"--warnon:3395";"--warnaserror+";"--define:NEGATIVE"] LangVersion.Preview "test" + singleVersionedNegTestAux "core/auto-widen/preview" ["--warnon:3388";"--warnon:3389";"--warnon:3395";"--warnaserror+";"--define:NEGATIVE"] LangVersion.V80 "test" [] let ``auto-widen-version-preview-default-warns``() = - singleVersionedNegTestAux "core/auto-widen/preview-default-warns" ["--warnaserror+";"--define:NEGATIVE"] LangVersion.Preview "test" + singleVersionedNegTestAux "core/auto-widen/preview-default-warns" ["--warnaserror+";"--define:NEGATIVE"] LangVersion.V80 "test" [] let ``comprehensions-FSC_DEBUG`` () = singleTestBuildAndRun "core/comprehensions" FSC_DEBUG From bc974da739e3594b2f5aa34f949c955f268f909e Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 26 Mar 2024 14:06:02 +0100 Subject: [PATCH 10/11] invetigate CI test failures --- .../Language/NullableReferenceTypesTests.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs index 2d2626aabbc..5e02d948c6b 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs @@ -9,7 +9,7 @@ let typeCheckWithStrictNullness cu = |> withCheckNulls |> withWarnOn 3261 |> withOptions ["--warnaserror+"] - |> typecheck + |> compile [] From 0a5b298860f751c51049ee743bcb6cebee395743 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 26 Mar 2024 20:30:54 +0100 Subject: [PATCH 11/11] warnon 3262 --- .../Language/NullableReferenceTypesTests.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs index 5e02d948c6b..1227fc44f47 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs @@ -8,6 +8,7 @@ let typeCheckWithStrictNullness cu = |> withLangVersionPreview |> withCheckNulls |> withWarnOn 3261 + |> withWarnOn 3262 |> withOptions ["--warnaserror+"] |> compile