Skip to content

Commit f1b9add

Browse files
authored
Nullness bugfix - change isObjTy early returns in ConstraintSolver (#17757)
1 parent dc2494a commit f1b9add

38 files changed

+1265
-722
lines changed

.fantomasignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ src/Compiler/Facilities/AsyncMemoize.fsi
117117
src/Compiler/Facilities/AsyncMemoize.fs
118118
src/Compiler/AbstractIL/il.fs
119119

120+
src/Compiler/Driver/GraphChecking/Graph.fsi
121+
src/Compiler/Driver/GraphChecking/Graph.fs
122+
120123
# Fantomas limitations on implementation files (to investigate)
121124

122125
src/Compiler/AbstractIL/ilwrite.fs

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
### Fixed
22

3+
* Fix false negatives for passing null to "obj" arguments. Only "obj | null" can now subsume any type ([PR #17757](https://github.com/dotnet/fsharp/pull/17757))
34
* Fix internal error when calling 'AddSingleton' and other overloads only differing in generic arity ([PR #17804](https://github.com/dotnet/fsharp/pull/17804))
45
* Fix extension methods support for non-reference system assemblies ([PR #17799](https://github.com/dotnet/fsharp/pull/17799))
56
* Ensure `frameworkTcImportsCache` mutations are thread-safe. ([PR #17795](https://github.com/dotnet/fsharp/pull/17795))
67
* Fix concurrency issue in `ILPreTypeDefImpl` ([PR #17812](https://github.com/dotnet/fsharp/pull/17812))
78

8-
99
### Added
1010

1111

src/Compiler/AbstractIL/ilreflect.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ type TypeBuilder with
277277

278278
match m with
279279
| null -> raise (MissingMethodException nm)
280-
| m -> m.Invoke(null, args)
280+
| m -> m.Invoke(null, (args: obj array))
281281

282282
member typB.SetCustomAttributeAndLog(cinfo, bytes) =
283283
if logRefEmitCalls then

src/Compiler/Checking/AttributeChecking.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,9 +466,9 @@ let MethInfoIsUnseen g (m: range) (ty: TType) minfo =
466466

467467
let isUnseenByHidingAttribute () =
468468
#if !NO_TYPEPROVIDERS
469-
not (isObjTy g ty) &&
469+
not (isObjTyAnyNullness g ty) &&
470470
isAppTy g ty &&
471-
isObjTy g minfo.ApparentEnclosingType &&
471+
isObjTyAnyNullness g minfo.ApparentEnclosingType &&
472472
let tcref = tcrefOfAppTy g ty
473473
match tcref.TypeReprInfo with
474474
| TProvidedTypeRepr info ->

src/Compiler/Checking/ConstraintSolver.fs

Lines changed: 650 additions & 637 deletions
Large diffs are not rendered by default.

src/Compiler/Checking/Expressions/CheckExpressions.fs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3283,7 +3283,7 @@ let AnalyzeArbitraryExprAsEnumerable (cenv: cenv) (env: TcEnv) localAlloc m expr
32833283

32843284
let enumElemTy =
32853285

3286-
if isObjTy g enumElemTy then
3286+
if isObjTyAnyNullness g enumElemTy then
32873287
// Look for an 'Item' property, or a set of these with consistent return types
32883288
let allEquivReturnTypes (minfo: MethInfo) (others: MethInfo list) =
32893289
let returnTy = minfo.GetFSharpReturnType(cenv.amap, m, [])
@@ -6195,7 +6195,7 @@ and TcExprObjectExpr (cenv: cenv) overallTy env tpenv (synObjTy, argopt, binds,
61956195
errorR(Error(FSComp.SR.tcCannotInheritFromErasedType(), m))
61966196
(m, intfTy, overrides), tpenv)
61976197

6198-
let realObjTy = if isObjTy g objTy && not (isNil extraImpls) then (p23 (List.head extraImpls)) else objTy
6198+
let realObjTy = if isObjTyAnyNullness g objTy && not (isNil extraImpls) then (p23 (List.head extraImpls)) else objTy
61996199

62006200
TcPropagatingExprLeafThenConvert cenv overallTy realObjTy env (* canAdhoc *) m (fun () ->
62016201
TcObjectExpr cenv env tpenv (objTy, realObjTy, argopt, binds, extraImpls, mObjTy, mNewExpr, m)
@@ -7320,7 +7320,7 @@ and TcFormatStringExpr cenv (overallTy: OverallTy) env m tpenv (fmtString: strin
73207320
let formatTy = mkPrintfFormatTy g aty bty cty dty ety
73217321

73227322
// This might qualify as a format string - check via a type directed rule
7323-
let ok = not (isObjTy g overallTy.Commit) && AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy.Commit formatTy
7323+
let ok = not (isObjTyAnyNullness g overallTy.Commit) && AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy.Commit formatTy
73247324

73257325
if ok then
73267326
// Parse the format string to work out the phantom types
@@ -7399,7 +7399,7 @@ and TcInterpolatedStringExpr cenv (overallTy: OverallTy) env m tpenv (parts: Syn
73997399
Choice1Of2 (true, newFormatMethod)
74007400

74017401
// ... or if that fails then may be a FormattableString by a type-directed rule....
7402-
elif (not (isObjTy g overallTy.Commit) &&
7402+
elif (not (isObjTyAnyNullness g overallTy.Commit) &&
74037403
((g.system_FormattableString_tcref.CanDeref && AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy.Commit g.system_FormattableString_ty)
74047404
|| (g.system_IFormattable_tcref.CanDeref && AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy.Commit g.system_IFormattable_ty))) then
74057405

@@ -7420,7 +7420,7 @@ and TcInterpolatedStringExpr cenv (overallTy: OverallTy) env m tpenv (parts: Syn
74207420
| None -> languageFeatureNotSupportedInLibraryError LanguageFeature.StringInterpolation m
74217421

74227422
// ... or if that fails then may be a PrintfFormat by a type-directed rule....
7423-
elif not (isObjTy g overallTy.Commit) && AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy.Commit formatTy then
7423+
elif not (isObjTyAnyNullness g overallTy.Commit) && AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy.Commit formatTy then
74247424

74257425
// And if that succeeds, the printerTy and printerResultTy must be the same (there are no curried arguments)
74267426
UnifyTypes cenv env m printerTy printerResultTy

src/Compiler/Checking/InfoReader.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1082,7 +1082,7 @@ let TryDestStandardDelegateType (infoReader: InfoReader) m ad delTy =
10821082
let g = infoReader.g
10831083
let (SigOfFunctionForDelegate(_, delArgTys, delRetTy, _)) = GetSigOfFunctionForDelegate infoReader delTy m ad
10841084
match delArgTys with
1085-
| senderTy :: argTys when (isObjTy g senderTy) && not (List.exists (isByrefTy g) argTys) -> Some(mkRefTupledTy g argTys, delRetTy)
1085+
| senderTy :: argTys when (isObjTyAnyNullness g senderTy) && not (List.exists (isByrefTy g) argTys) -> Some(mkRefTupledTy g argTys, delRetTy)
10861086
| _ -> None
10871087

10881088

src/Compiler/Checking/MethodCalls.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1319,7 +1319,7 @@ let BuildNewDelegateExpr (eventInfoOpt: EventInfo option, g, amap, delegateTy, d
13191319
| Some einfo ->
13201320
match delArgVals with
13211321
| [] -> error(nonStandardEventError einfo.EventName m)
1322-
| h :: _ when not (isObjTy g h.Type) -> error(nonStandardEventError einfo.EventName m)
1322+
| h :: _ when not (isObjTyAnyNullness g h.Type) -> error(nonStandardEventError einfo.EventName m)
13231323
| h :: t -> [exprForVal m h; mkRefTupledVars g m t]
13241324
| None ->
13251325
if isNil delArgTys then [mkUnit g m] else List.map (exprForVal m) delArgVals

src/Compiler/Checking/NameResolution.fs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4422,14 +4422,14 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv (completionTargets: Reso
44224422
//
44234423
// Don't show GetHashCode or Equals for F# types that admit equality as an abnormal operation
44244424
let isUnseenDueToBasicObjRules =
4425-
not (isObjTy g ty) &&
4425+
not (isObjTyAnyNullness g ty) &&
44264426
not minfo.IsExtensionMember &&
44274427
match minfo.LogicalName with
44284428
| "GetType" -> false
4429-
| "GetHashCode" -> isObjTy g minfo.ApparentEnclosingType && not (AugmentTypeDefinitions.TypeDefinitelyHasEquality g ty)
4429+
| "GetHashCode" -> isObjTyAnyNullness g minfo.ApparentEnclosingType && not (AugmentTypeDefinitions.TypeDefinitelyHasEquality g ty)
44304430
| "ToString" -> false
44314431
| "Equals" ->
4432-
if not (isObjTy g minfo.ApparentEnclosingType) then
4432+
if not (isObjTyAnyNullness g minfo.ApparentEnclosingType) then
44334433
// declaring type is not System.Object - show it
44344434
false
44354435
elif minfo.IsInstance then
@@ -4440,7 +4440,7 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv (completionTargets: Reso
44404440
true
44414441
| _ ->
44424442
// filter out self methods of obj type
4443-
isObjTy g minfo.ApparentEnclosingType
4443+
isObjTyAnyNullness g minfo.ApparentEnclosingType
44444444

44454445
let result =
44464446
not isUnseenDueToBasicObjRules &&
@@ -5121,14 +5121,14 @@ let ResolveCompletionsInTypeForItem (ncenv: NameResolver) nenv m ad statics ty (
51215121
//
51225122
// Don't show GetHashCode or Equals for F# types that admit equality as an abnormal operation
51235123
let isUnseenDueToBasicObjRules =
5124-
not (isObjTy g ty) &&
5124+
not (isObjTyAnyNullness g ty) &&
51255125
not minfo.IsExtensionMember &&
51265126
match minfo.LogicalName with
51275127
| "GetType" -> false
5128-
| "GetHashCode" -> isObjTy g minfo.ApparentEnclosingType && not (AugmentTypeDefinitions.TypeDefinitelyHasEquality g ty)
5128+
| "GetHashCode" -> isObjTyAnyNullness g minfo.ApparentEnclosingType && not (AugmentTypeDefinitions.TypeDefinitelyHasEquality g ty)
51295129
| "ToString" -> false
51305130
| "Equals" ->
5131-
if not (isObjTy g minfo.ApparentEnclosingType) then
5131+
if not (isObjTyAnyNullness g minfo.ApparentEnclosingType) then
51325132
// declaring type is not System.Object - show it
51335133
false
51345134
elif minfo.IsInstance then
@@ -5139,7 +5139,7 @@ let ResolveCompletionsInTypeForItem (ncenv: NameResolver) nenv m ad statics ty (
51395139
true
51405140
| _ ->
51415141
// filter out self methods of obj type
5142-
isObjTy g minfo.ApparentEnclosingType
5142+
isObjTyAnyNullness g minfo.ApparentEnclosingType
51435143
let result =
51445144
not isUnseenDueToBasicObjRules &&
51455145
not minfo.IsInstance = statics &&

src/Compiler/Checking/NicePrint.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2191,7 +2191,7 @@ module TastDefinitionPrinting =
21912191
let inherits =
21922192
[ if not (suppressInheritanceAndInterfacesForTyInSimplifiedDisplays g amap m ty) then
21932193
match GetSuperTypeOfType g amap m ty with
2194-
| Some superTy when not (isObjTy g superTy) && not (isValueTypeTy g superTy) ->
2194+
| Some superTy when not (isObjTyAnyNullness g superTy) && not (isValueTypeTy g superTy) ->
21952195
superTy
21962196
| _ -> ()
21972197
]

0 commit comments

Comments
 (0)