Skip to content

Commit 841ba8e

Browse files
authored
Bugfix :: Nullness in signature file is not considered by implementation and vice versa (#18186)
1 parent 674e099 commit 841ba8e

File tree

92 files changed

+639
-323
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+639
-323
lines changed

.fantomasignore

+5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ src/Compiler/Checking/TypeRelations.fs
4242

4343
# nullness-related problems
4444
src/Compiler/DependencyManager/DependencyProvider.fs
45+
src/FSharp.Core/fslib-extra-pervasives.fs
46+
src/FSharp.Core/fslib-extra-pervasives.fsi
4547

4648
# Incorrectly formatted: https://github.com/dotnet/fsharp/pull/14645/commits/49443a67ea8a17670c8a7c80c8bdf91f82231e91 or https://github.com/fsprojects/fantomas/issues/2733
4749
# This CompilerImports.fs behavior is not fixed yet, following up in https://github.com/fsprojects/fantomas/issues/2733
@@ -124,6 +126,9 @@ src/Compiler/SyntaxTree/LexerStore.fs
124126
src/Compiler/Driver/GraphChecking/Graph.fsi
125127
src/Compiler/Driver/GraphChecking/Graph.fs
126128

129+
src/Compiler/DependencyManager/NativeDllResolveHandler.fsi
130+
src/Compiler/DependencyManager/AssemblyResolveHandler.fsi
131+
127132
# Fantomas limitations on implementation files (to investigate)
128133

129134
src/Compiler/AbstractIL/ilwrite.fs

docs/release-notes/.FSharp.Compiler.Service/9.0.300.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
### Added
1212
* Added missing type constraints in FCS. ([PR #18241](https://github.com/dotnet/fsharp/pull/18241))
1313
* The 'use' keyword can be used on IDisposable|null without nullness warnings ([PR #18262](https://github.com/dotnet/fsharp/pull/18262))
14+
* Nullness warnings are issued for signature<>implementation conformance ([PR #18186](https://github.com/dotnet/fsharp/pull/18186))
1415
* Symbols: Add FSharpAssembly.IsFSharp ([PR #18290](https://github.com/dotnet/fsharp/pull/18290))
1516

1617
### Changed

src/Compiler/AbstractIL/ilreflect.fs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2548,7 +2548,7 @@ let EmitDynamicAssemblyFragment
25482548
ignore (typB.InvokeMemberAndLog(methodName, BindingFlags.InvokeMethod ||| BindingFlags.Public ||| BindingFlags.Static, [||]))
25492549
None
25502550
with :? TargetInvocationException as exn ->
2551-
Some exn.InnerException
2551+
Option.ofObj exn.InnerException
25522552

25532553
let emEnv, entryPts = envPopEntryPts emEnv
25542554
let execs = List.map execEntryPtFun entryPts

src/Compiler/Checking/AttributeChecking.fsi

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ type AttribInfo =
2424
| FSAttribInfo of TcGlobals * Attrib
2525
| ILAttribInfo of TcGlobals * Import.ImportMap * ILScopeRef * ILAttribute * range
2626

27-
member ConstructorArguments: (TType * obj) list
28-
member NamedArguments: (TType * string * bool * obj) list
27+
member ConstructorArguments: (TType * objnull) list
28+
member NamedArguments: (TType * string * bool * objnull) list
2929
member Range: range
3030
member TyconRef: TyconRef
3131

src/Compiler/Checking/CheckDeclarations.fs

+6-6
Original file line numberDiff line numberDiff line change
@@ -3060,7 +3060,7 @@ module EstablishTypeDefinitionCores =
30603060

30613061
if not isRootGenerated then
30623062
let desig = theRootTypeWithRemapping.TypeProviderDesignation
3063-
let nm = theRootTypeWithRemapping.PUntaint((fun st -> st.FullName), m)
3063+
let nm = theRootTypeWithRemapping.PUntaint((fun st -> string st.FullName), m)
30643064
error(Error(FSComp.SR.etErasedTypeUsedInGeneration(desig, nm), m))
30653065

30663066
cenv.createsGeneratedProvidedTypes <- true
@@ -3101,7 +3101,7 @@ module EstablishTypeDefinitionCores =
31013101

31023102
if not isGenerated then
31033103
let desig = st.TypeProviderDesignation
3104-
let nm = st.PUntaint((fun st -> st.FullName), m)
3104+
let nm = st.PUntaint((fun st -> string st.FullName), m)
31053105
error(Error(FSComp.SR.etErasedTypeUsedInGeneration(desig, nm), m))
31063106

31073107
// Embed the type into the module we're compiling
@@ -4251,7 +4251,7 @@ module TcDeclarations =
42514251
// For historical reasons we only give a warning for incorrect type parameters on intrinsic extensions
42524252
if nReqTypars <> synTypars.Length then
42534253
errorR(Error(FSComp.SR.tcDeclaredTypeParametersForExtensionDoNotMatchOriginal(tcref.DisplayNameWithStaticParametersAndUnderscoreTypars), m))
4254-
if not (typarsAEquiv g TypeEquivEnv.Empty reqTypars declaredTypars) then
4254+
if not (typarsAEquiv g (TypeEquivEnv.EmptyWithNullChecks g) reqTypars declaredTypars) then
42554255
warning(Error(FSComp.SR.tcDeclaredTypeParametersForExtensionDoNotMatchOriginal(tcref.DisplayNameWithStaticParametersAndUnderscoreTypars), m))
42564256
// Note we return 'reqTypars' for intrinsic extensions since we may only have given warnings
42574257
IntrinsicExtensionBinding, reqTypars
@@ -4260,7 +4260,7 @@ module TcDeclarations =
42604260
errorR(Error(FSComp.SR.tcMembersThatExtendInterfaceMustBePlacedInSeparateModule(), tcref.Range))
42614261
if nReqTypars <> synTypars.Length then
42624262
error(Error(FSComp.SR.tcDeclaredTypeParametersForExtensionDoNotMatchOriginal(tcref.DisplayNameWithStaticParametersAndUnderscoreTypars), m))
4263-
if not (typarsAEquiv g TypeEquivEnv.Empty reqTypars declaredTypars) then
4263+
if not (typarsAEquiv g (TypeEquivEnv.EmptyWithNullChecks g) reqTypars declaredTypars) then
42644264
errorR(Error(FSComp.SR.tcDeclaredTypeParametersForExtensionDoNotMatchOriginal(tcref.DisplayNameWithStaticParametersAndUnderscoreTypars), m))
42654265
ExtrinsicExtensionBinding, declaredTypars
42664266

@@ -5702,7 +5702,7 @@ let CheckModuleSignature g (cenv: cenv) m denvAtEnd rootSigOpt implFileTypePrior
57025702
|]
57035703

57045704
// We want to show imperative type variables in any types in error messages at this late point
5705-
let denv = { denvAtEnd with showInferenceTyparAnnotations=true }
5705+
let denv = { denvAtEnd with showInferenceTyparAnnotations=true;showNullnessAnnotations=Some g.checkNullness }
57065706
try
57075707

57085708
// As typechecked the signature and implementation use different tycons etc.
@@ -5714,7 +5714,7 @@ let CheckModuleSignature g (cenv: cenv) m denvAtEnd rootSigOpt implFileTypePrior
57145714
// Compute the remapping from implementation to signature
57155715
let remapInfo, _ = ComputeRemappingFromInferredSignatureToExplicitSignature g implFileTypePriorToSig sigFileType
57165716

5717-
let aenv = { TypeEquivEnv.Empty with EquivTycons = TyconRefMap.OfList remapInfo.RepackagedEntities }
5717+
let aenv = { TypeEquivEnv.EmptyWithNullChecks g with EquivTycons = TyconRefMap.OfList remapInfo.RepackagedEntities }
57185718

57195719
if not (SignatureConformance.Checker(g, cenv.amap, denv, remapInfo, true).CheckSignature aenv cenv.infoReader (mkLocalModuleRef implFileSpecPriorToSig) sigFileType) then
57205720
// We can just raise 'ReportedError' since CheckModuleOrNamespace raises its own error

src/Compiler/Checking/ConstraintSolver.fs

+1-1
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ let MakeConstraintSolverEnv contextInfo css m denv =
345345
eContextInfo = contextInfo
346346
MatchingOnly = false
347347
ErrorOnFailedMemberConstraintResolution = false
348-
EquivEnv = TypeEquivEnv.Empty
348+
EquivEnv = TypeEquivEnv.EmptyIgnoreNulls
349349
DisplayEnv = denv
350350
IsSpeculativeForMethodOverloading = false
351351
IsSupportsNullFlex = false

src/Compiler/Checking/Expressions/CheckExpressions.fs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12687,7 +12687,7 @@ and FixupLetrecBind (cenv: cenv) denv generalizedTyparsForRecursiveBlock (bind:
1268712687
| Some _ ->
1268812688
match PartitionValTyparsForApparentEnclosingType g vspec with
1268912689
| Some(parentTypars, memberParentTypars, _, _, _) ->
12690-
ignore(SignatureConformance.Checker(g, cenv.amap, denv, SignatureRepackageInfo.Empty, false).CheckTypars vspec.Range TypeEquivEnv.Empty memberParentTypars parentTypars)
12690+
ignore(SignatureConformance.Checker(g, cenv.amap, denv, SignatureRepackageInfo.Empty, false).CheckTypars vspec.Range TypeEquivEnv.EmptyIgnoreNulls memberParentTypars parentTypars)
1269112691
| None ->
1269212692
errorR(Error(FSComp.SR.tcMemberIsNotSufficientlyGeneric(), vspec.Range))
1269312693
| _ -> ()

src/Compiler/Checking/InfoReader.fs

+2-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ let rec GetImmediateIntrinsicMethInfosOfTypeAux (optFilter, ad) g amap m withExp
6363
let st = info.ProvidedType
6464
let meths =
6565
match optFilter with
66-
| Some name -> st.PApplyArray ((fun st -> st.GetMethods() |> Array.filter (fun mi -> mi.Name = name) ), "GetMethods", m)
66+
| Some name ->
67+
st.PApplyFilteredArray ((fun st -> st.GetMethods()),(fun mi -> mi.Name = name), "GetMethods", m)
6768
| None -> st.PApplyArray ((fun st -> st.GetMethods()), "GetMethods", m)
6869
[ for mi in meths -> ProvidedMeth(amap, mi.Coerce(m), None, m) ]
6970
#endif

src/Compiler/Checking/MethodCalls.fs

+7-7
Original file line numberDiff line numberDiff line change
@@ -1120,7 +1120,7 @@ let TryImportProvidedMethodBaseAsLibraryIntrinsic (amap: Import.ImportMap, m: ra
11201120
match tryTcrefOfAppTy amap.g declaringType with
11211121
| ValueSome declaringEntity ->
11221122
if not declaringEntity.IsLocalRef && ccuEq declaringEntity.nlr.Ccu amap.g.fslibCcu then
1123-
let n = mbase.PUntaint((fun x -> x.GetParameters().Length), m)
1123+
let n = mbase.PApplyArray((fun x -> x.GetParameters()),"GetParameters", m).Length
11241124
match amap.g.knownIntrinsics.TryGetValue ((declaringEntity.LogicalName, None, methodName, n)) with
11251125
| true, vref -> Some vref
11261126
| _ ->
@@ -1815,14 +1815,14 @@ module ProvidedMethodCalls =
18151815
let rec loop (st: Tainted<ProvidedType>) =
18161816
if st.PUntaint((fun st -> st.IsGenericParameter), m) then st
18171817
elif st.PUntaint((fun st -> st.IsArray), m) then
1818-
let et = st.PApply((fun st -> st.GetElementType()), m)
1818+
let et = st.PApply((fun st -> !! st.GetElementType()), m)
18191819
let rank = st.PUntaint((fun st -> st.GetArrayRank()), m)
18201820
(loop et).PApply((fun st -> if rank = 1 then st.MakeArrayType() else st.MakeArrayType(rank)), m)
18211821
elif st.PUntaint((fun st -> st.IsByRef), m) then
1822-
let et = st.PApply((fun st -> st.GetElementType()), m)
1822+
let et = st.PApply((fun st -> !! st.GetElementType()), m)
18231823
(loop et).PApply((fun st -> st.MakeByRefType()), m)
18241824
elif st.PUntaint((fun st -> st.IsPointer), m) then
1825-
let et = st.PApply((fun st -> st.GetElementType()), m)
1825+
let et = st.PApply((fun st -> !! st.GetElementType()), m)
18261826
(loop et).PApply((fun st -> st.MakePointerType()), m)
18271827
else
18281828
let isGeneric = st.PUntaint((fun st -> st.IsGenericType), m)
@@ -1863,7 +1863,7 @@ module ProvidedMethodCalls =
18631863
allArgs: Exprs,
18641864
paramVars: Tainted<ProvidedVar>[],
18651865
g, amap, mut, isProp, isSuperInit, m,
1866-
expr: Tainted<ProvidedExpr>) =
1866+
expr: Tainted<ProvidedExpr MaybeNull>) =
18671867

18681868
let varConv =
18691869
// note: Assuming the size based on paramVars
@@ -1873,7 +1873,7 @@ module ProvidedMethodCalls =
18731873
dict.Add(v, (None, e))
18741874
dict
18751875

1876-
let rec exprToExprAndWitness top (ea: Tainted<ProvidedExpr>) =
1876+
let rec exprToExprAndWitness top (ea: Tainted<ProvidedExpr MaybeNull>) =
18771877
let fail() = error(Error(FSComp.SR.etUnsupportedProvidedExpression(ea.PUntaint((fun etree -> etree.UnderlyingExpressionString), m)), m))
18781878
match ea with
18791879
| Tainted.Null -> error(Error(FSComp.SR.etNullProvidedExpression(ea.TypeProviderDesignation), m))
@@ -2115,7 +2115,7 @@ module ProvidedMethodCalls =
21152115
methInfoOpt, expr, exprTy
21162116
with
21172117
| :? TypeProviderError as tpe ->
2118-
let typeName = mi.PUntaint((fun mb -> (nonNull<ProvidedType> mb.DeclaringType).FullName), m)
2118+
let typeName = mi.PUntaint((fun mb -> (nonNull<ProvidedType> mb.DeclaringType).FullName |> string), m)
21192119
let methName = mi.PUntaint((fun mb -> mb.Name), m)
21202120
raise( tpe.WithContext(typeName, methName) ) // loses original stack trace
21212121
#endif

src/Compiler/Checking/MethodOverrides.fs

+2-2
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ module DispatchSlotChecking =
269269
// Compare the types. CompiledSigOfMeth, GetObjectExprOverrideInfo and GetTypeMemberOverrideInfo have already
270270
// applied all relevant substitutions except the renamings from fvtmps <-> methTypars
271271

272-
let aenv = TypeEquivEnv.FromEquivTypars fvmethTypars methTypars
272+
let aenv = (TypeEquivEnv.EmptyIgnoreNulls).FromEquivTypars fvmethTypars methTypars
273273

274274
List.forall2 (List.lengthsEqAndForall2 (typeAEquiv g aenv)) vargTys argTys &&
275275
returnTypesAEquiv g aenv vrty retTy &&
@@ -305,7 +305,7 @@ module DispatchSlotChecking =
305305
ComposeTyparInsts ttpinst (ReverseTyparRenaming g memberToParentInst)
306306

307307
// Compare under the composed substitutions
308-
let aenv = TypeEquivEnv.FromTyparInst ttpinst
308+
let aenv = (TypeEquivEnv.EmptyIgnoreNulls).FromTyparInst ttpinst
309309

310310
typarsAEquiv g aenv fvmethTypars methTypars
311311

src/Compiler/Checking/NameResolution.fs

+1-1
Original file line numberDiff line numberDiff line change
@@ -991,7 +991,7 @@ let ResolveProvidedTypeNameInEntity (amap, m, typeName, modref: ModuleOrNamespac
991991
//if staticResInfo.NumStaticArgs > 0 then
992992
// error(Error(FSComp.SR.etNestedProvidedTypesDoNotTakeStaticArgumentsOrGenericParameters(), m))
993993
[]
994-
| nestedSty ->
994+
| Tainted.NonNull nestedSty ->
995995
[AddEntityForProvidedType (amap, modref, resolutionEnvironment, nestedSty, m) ]
996996
| _ -> []
997997
#endif

src/Compiler/Checking/NicePrint.fs

+3-3
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,7 @@ module PrintTypes =
764764
|> ListSet.setify (fun (_, cx1) (_, cx2) ->
765765
match cx1, cx2 with
766766
| TyparConstraint.MayResolveMember(traitInfo1, _),
767-
TyparConstraint.MayResolveMember(traitInfo2, _) -> traitsAEquiv denv.g TypeEquivEnv.Empty traitInfo1 traitInfo2
767+
TyparConstraint.MayResolveMember(traitInfo2, _) -> traitsAEquiv denv.g (TypeEquivEnv.EmptyWithNullChecks denv.g) traitInfo1 traitInfo2
768768
| _ -> false)
769769

770770
let cxsL = List.collect (layoutConstraintWithInfo denv env) cxs
@@ -2177,7 +2177,7 @@ module TastDefinitionPrinting =
21772177
match tcref.TypeReprInfo with
21782178
| TProvidedTypeRepr info ->
21792179
[
2180-
for nestedType in info.ProvidedType.PApplyArray((fun sty -> sty.GetNestedTypes() |> Array.filter (fun t -> t.IsPublic || t.IsNestedPublic)), "GetNestedTypes", m) do
2180+
for nestedType in info.ProvidedType.PApplyFilteredArray((fun sty -> sty.GetNestedTypes()),(fun t -> t.IsPublic || t.IsNestedPublic), "GetNestedTypes", m) do
21812181
yield nestedType.PUntaint((fun t -> t.IsClass, t.Name), m)
21822182
]
21832183
|> List.sortBy snd
@@ -2930,7 +2930,7 @@ let minimalStringsOfTwoTypes denv ty1 ty2 =
29302930
let denv = denv.SetOpenPaths []
29312931
let denv = { denv with includeStaticParametersInTypeNames=true }
29322932
let makeName t =
2933-
let assemblyName = PrintTypes.layoutAssemblyName denv t |> function Null | NonNull "" -> "" | NonNull name -> sprintf " (%s)" name
2933+
let assemblyName = PrintTypes.layoutAssemblyName denv t |> function | "" -> "" | name -> $" (%s{name})"
29342934
sprintf "%s%s" (stringOfTy denv t) assemblyName
29352935

29362936
(makeName ty1, makeName ty2, stringOfTyparConstraints denv tpcs)

0 commit comments

Comments
 (0)