Skip to content

Commit 7408e8f

Browse files
authored
Nullness FS3261: pinpoint receiver range, name the member & binding in dot-access warnings (#19814)
1 parent b6810c2 commit 7408e8f

54 files changed

Lines changed: 762 additions & 272 deletions

Some content is hidden

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

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@
102102
* Debug: fix if and match condition sequence points ([PR #19932](https://github.com/dotnet/fsharp/pull/19932))
103103
* Checker: recover on checking language version ([PR ##19970](https://github.com/dotnet/fsharp/pull/19970))
104104

105+
### Improved
106+
107+
* Nullness warning FS3261 on dotted method or property access (e.g. `x.Member`) now underlines the receiver expression and includes the member name and (when known) the binding name in the message. ([Issue #19658](https://github.com/dotnet/fsharp/issues/19658), [PR #19814](https://github.com/dotnet/fsharp/pull/19814))
108+
105109
### Changed
106110

107111
* Improvements in error and warning messages: new error FS3885 when `let!`/`use!` is the final expression in a computation expression; new warning FS3886 when a list literal contains a single tuple element (likely missing `;` separator); improved wording for FS0003, FS0025, FS0039, FS0072, FS0247, FS0597, FS0670, FS3082, and SRTP operator-not-in-scope hints. ([PR #19398](https://github.com/dotnet/fsharp/pull/19398))

src/Compiler/Checking/AugmentWithHashCompare.fs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,7 +1241,7 @@ let unaryArg = [ ValReprInfo.unnamedTopArg ]
12411241
let tupArg = [ [ ValReprInfo.unnamedTopArg1; ValReprInfo.unnamedTopArg1 ] ]
12421242

12431243
let mkValSpecAux g m (tcref: TyconRef) ty vis slotsig methn valTy argData isGetter isCompGen =
1244-
let tps = tcref.Typars m
1244+
let tps = tcref.Typars
12451245

12461246
let membInfo =
12471247
match slotsig with
@@ -1298,18 +1298,16 @@ let mkImpliedValSpec g m tcref ty vis slotsig methn valTy argData isGetter =
12981298
v
12991299

13001300
let MakeValsForCompareAugmentation g (tcref: TyconRef) =
1301-
let m = tcref.Range
13021301
let _, ty = mkMinimalTy g tcref
1303-
let tps = tcref.Typars m
1302+
let tps = tcref.Typars
13041303
let vis = tcref.TypeReprAccessibility
13051304

13061305
mkValSpec g tcref ty vis (Some(mkIComparableCompareToSlotSig g)) "CompareTo" (tps +-> (mkCompareObjTy g ty)) unaryArg false,
13071306
mkValSpec g tcref ty vis (Some(mkGenericIComparableCompareToSlotSig g ty)) "CompareTo" (tps +-> (mkCompareTy g ty)) unaryArg false
13081307

13091308
let MakeValsForCompareWithComparerAugmentation g (tcref: TyconRef) =
1310-
let m = tcref.Range
13111309
let _, ty = mkMinimalTy g tcref
1312-
let tps = tcref.Typars m
1310+
let tps = tcref.Typars
13131311
let vis = tcref.TypeReprAccessibility
13141312

13151313
mkValSpec
@@ -1324,10 +1322,9 @@ let MakeValsForCompareWithComparerAugmentation g (tcref: TyconRef) =
13241322
false
13251323

13261324
let MakeValsForEqualsAugmentation g (tcref: TyconRef) =
1327-
let m = tcref.Range
13281325
let _, ty = mkMinimalTy g tcref
13291326
let vis = tcref.Accessibility
1330-
let tps = tcref.Typars m
1327+
let tps = tcref.Typars
13311328

13321329
let objEqualsVal =
13331330
mkValSpec g tcref ty vis (Some(mkEqualsSlotSig g)) "Equals" (tps +-> (mkEqualsObjTy g ty)) unaryArg false
@@ -1352,7 +1349,7 @@ let MakeValsForEqualsAugmentation g (tcref: TyconRef) =
13521349
let MakeValsForEqualityWithComparerAugmentation g (tcref: TyconRef) =
13531350
let _, ty = mkMinimalTy g tcref
13541351
let vis = tcref.Accessibility
1355-
let tps = tcref.Typars tcref.Range
1352+
let tps = tcref.Typars
13561353

13571354
let objGetHashCodeVal =
13581355
mkValSpec g tcref ty vis (Some(mkGetHashCodeSlotSig g)) "GetHashCode" (tps +-> (mkHashTy g ty)) unitArg false
@@ -1395,7 +1392,7 @@ let MakeValsForEqualityWithComparerAugmentation g (tcref: TyconRef) =
13951392
let MakeBindingsForCompareAugmentation g (tycon: Tycon) =
13961393
let tcref = mkLocalTyconRef tycon
13971394
let m = tycon.Range
1398-
let tps = tycon.Typars m
1395+
let tps = tycon.Typars
13991396

14001397
let mkCompare comparef =
14011398
match tycon.GeneratedCompareToValues with
@@ -1439,7 +1436,7 @@ let MakeBindingsForCompareAugmentation g (tycon: Tycon) =
14391436
let MakeBindingsForCompareWithComparerAugmentation g (tycon: Tycon) =
14401437
let tcref = mkLocalTyconRef tycon
14411438
let m = tycon.Range
1442-
let tps = tycon.Typars m
1439+
let tps = tycon.Typars
14431440

14441441
let mkCompare comparef =
14451442
match tycon.GeneratedCompareToWithComparerValues with
@@ -1471,7 +1468,7 @@ let MakeBindingsForCompareWithComparerAugmentation g (tycon: Tycon) =
14711468
let MakeBindingsForEqualityWithComparerAugmentation (g: TcGlobals) (tycon: Tycon) =
14721469
let tcref = mkLocalTyconRef tycon
14731470
let m = tycon.Range
1474-
let tps = tycon.Typars m
1471+
let tps = tycon.Typars
14751472

14761473
let mkStructuralEquatable hashf equalsf =
14771474
match tycon.GeneratedHashAndEqualsWithComparerValues with
@@ -1590,7 +1587,7 @@ let MakeBindingsForEqualityWithComparerAugmentation (g: TcGlobals) (tycon: Tycon
15901587
let MakeBindingsForEqualsAugmentation (g: TcGlobals) (tycon: Tycon) =
15911588
let tcref = mkLocalTyconRef tycon
15921589
let m = tycon.Range
1593-
let tps = tycon.Typars m
1590+
let tps = tycon.Typars
15941591

15951592
let mkEquals equalsf =
15961593
match tycon.GeneratedHashAndEqualsValues with
@@ -1668,15 +1665,15 @@ let rec TypeDefinitelyHasEquality g ty =
16681665
)
16691666
&&
16701667
// Check the (possibly inferred) structural dependencies
1671-
(tinst, tcref.TyparsNoRange)
1668+
(tinst, tcref.Typars)
16721669
||> List.lengthsEqAndForall2 (fun ty tp -> not tp.EqualityConditionalOn || TypeDefinitelyHasEquality g ty)
16731670
| _ -> false
16741671

16751672
let MakeValsForUnionAugmentation g (tcref: TyconRef) =
16761673
let m = tcref.Range
16771674
let _, tmty = mkMinimalTy g tcref
16781675
let vis = tcref.TypeReprAccessibility
1679-
let tps = tcref.Typars m
1676+
let tps = tcref.Typars
16801677

16811678
tcref.UnionCasesAsList
16821679
|> List.map (fun uc ->
@@ -1690,7 +1687,7 @@ let MakeValsForUnionAugmentation g (tcref: TyconRef) =
16901687
let MakeBindingsForUnionAugmentation g (tycon: Tycon) (vals: ValRef list) =
16911688
let tcref = mkLocalTyconRef tycon
16921689
let m = tycon.Range
1693-
let tps = tycon.Typars m
1690+
let tps = tycon.Typars
16941691
let tinst, ty = mkMinimalTy g tcref
16951692
let thisv, thise = mkThisVar g m ty
16961693
let unitv, _ = mkCompGenLocal m "unitArg" g.unit_ty

src/Compiler/Checking/CheckDeclarations.fs

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,7 +1701,7 @@ module MutRecBindingChecking =
17011701
let thisValOpt = GetInstanceMemberThisVariable (v, x)
17021702

17031703
// Members have at least as many type parameters as the enclosing class. Just grab the type variables for the type.
1704-
let thisTyInst = List.map mkTyparTy (List.truncate (tcref.Typars(v.Range).Length) v.Typars)
1704+
let thisTyInst = List.map mkTyparTy (List.truncate (tcref.Typars.Length) v.Typars)
17051705

17061706
let x = localReps.FixupIncrClassExprPhase2C cenv thisValOpt safeStaticInitInfo thisTyInst x
17071707

@@ -2153,7 +2153,7 @@ module TyconConstraintInference =
21532153
| ValueSome tp ->
21542154
// Within structural types, type parameters can be optimistically assumed to have comparison
21552155
// We record the ones for which we have made this assumption.
2156-
if tycon.TyparsNoRange |> List.exists (fun tp2 -> typarRefEq tp tp2) then
2156+
if tycon.Typars |> List.exists (fun tp2 -> typarRefEq tp tp2) then
21572157
assumedTyparsAcc <- assumedTyparsAcc.Add(tp.Stamp)
21582158
true
21592159
else
@@ -2180,7 +2180,7 @@ module TyconConstraintInference =
21802180
not (EntityHasWellKnownAttribute g WellKnownEntityAttributes.NoComparisonAttribute tcref.Deref)
21812181
&&
21822182
// Check the structural dependencies
2183-
(tinst, tcref.TyparsNoRange) ||> List.lengthsEqAndForall2 (fun ty tp ->
2183+
(tinst, tcref.Typars) ||> List.lengthsEqAndForall2 (fun ty tp ->
21842184
if tp.ComparisonConditionalOn || assumedTypars.Contains tp.Stamp then
21852185
checkIfFieldTypeSupportsComparison tycon ty
21862186
else
@@ -2239,7 +2239,7 @@ module TyconConstraintInference =
22392239
// OK, we're done, Record the results for the type variable which provide the support
22402240
for tyconStamp in uneliminatedTycons do
22412241
let tycon, _ = tab[tyconStamp]
2242-
for tp in tycon.Typars(tycon.Range) do
2242+
for tp in tycon.Typars do
22432243
if assumedTyparsActual.Contains(tp.Stamp) then
22442244
tp.SetComparisonDependsOn true
22452245

@@ -2274,7 +2274,7 @@ module TyconConstraintInference =
22742274
| ValueSome tp ->
22752275
// Within structural types, type parameters can be optimistically assumed to have equality
22762276
// We record the ones for which we have made this assumption.
2277-
if tycon.Typars(tycon.Range) |> List.exists (fun tp2 -> typarRefEq tp tp2) then
2277+
if tycon.Typars |> List.exists (fun tp2 -> typarRefEq tp tp2) then
22782278
assumedTyparsAcc <- assumedTyparsAcc.Add(tp.Stamp)
22792279
true
22802280
else
@@ -2300,7 +2300,7 @@ module TyconConstraintInference =
23002300
not (EntityHasWellKnownAttribute g WellKnownEntityAttributes.NoEqualityAttribute tcref.Deref)
23012301
&&
23022302
// Check the structural dependencies
2303-
(tinst, tcref.TyparsNoRange) ||> List.lengthsEqAndForall2 (fun ty tp ->
2303+
(tinst, tcref.Typars) ||> List.lengthsEqAndForall2 (fun ty tp ->
23042304
if tp.EqualityConditionalOn || assumedTypars.Contains tp.Stamp then
23052305
checkIfFieldTypeSupportsEquality tycon ty
23062306
else
@@ -2360,7 +2360,7 @@ module TyconConstraintInference =
23602360
// OK, we're done, Record the results for the type variable which provide the support
23612361
for tyconStamp in uneliminatedTycons do
23622362
let tycon, _ = tab[tyconStamp]
2363-
for tp in tycon.Typars(tycon.Range) do
2363+
for tp in tycon.Typars do
23642364
if assumedTyparsActual.Contains(tp.Stamp) then
23652365
tp.SetEqualityDependsOn true
23662366

@@ -2604,8 +2604,7 @@ module EstablishTypeDefinitionCores =
26042604
let private GetStructuralElementsOfTyconDefn (cenv: cenv) env tpenv (MutRecDefnsPhase1DataForTycon(_, synTyconRepr, _, _, _, _)) tycon =
26052605
let thisTyconRef = mkLocalTyconRef tycon
26062606
let g = cenv.g
2607-
let m = tycon.Range
2608-
let env = AddDeclaredTypars CheckForDuplicateTypars (tycon.Typars m) env
2607+
let env = AddDeclaredTypars CheckForDuplicateTypars (tycon.Typars) env
26092608
let env = MakeInnerEnvForTyconRef env thisTyconRef false
26102609
[ match synTyconRepr with
26112610
| SynTypeDefnSimpleRepr.None _ -> ()
@@ -2646,7 +2645,7 @@ module EstablishTypeDefinitionCores =
26462645
for arg in ctorArgNames do
26472646
let ty = names[arg].Type
26482647
let m = names[arg].Ident.idRange
2649-
if not (isNil (ListSet.subtract typarEq (freeInTypeLeftToRight g false ty) tycon.TyparsNoRange)) then
2648+
if not (isNil (ListSet.subtract typarEq (freeInTypeLeftToRight g false ty) tycon.Typars)) then
26502649
errorR(Error(FSComp.SR.tcStructsMustDeclareTypesOfImplicitCtorArgsExplicitly(), m))
26512650
yield (ty, m)
26522651

@@ -3215,7 +3214,7 @@ module EstablishTypeDefinitionCores =
32153214

32163215
let hasMeasureAttr = attribsHaveEntityFlag g WellKnownEntityAttributes.MeasureAttribute attrs
32173216
let hasMeasureableAttr = attribsHaveEntityFlag g WellKnownEntityAttributes.MeasureableAttribute attrs
3218-
let envinner = AddDeclaredTypars CheckForDuplicateTypars (tycon.Typars m) envinner
3217+
let envinner = AddDeclaredTypars CheckForDuplicateTypars (tycon.Typars) envinner
32193218
let envinner = MakeInnerEnvForTyconRef envinner thisTyconRef false
32203219

32213220
match synTyconRepr with
@@ -3226,7 +3225,7 @@ module EstablishTypeDefinitionCores =
32263225
// "type x = | A" can always be used instead.
32273226
| TyconCoreAbbrevThatIsReallyAUnion (hasMeasureAttr, envinner, id) _ -> ()
32283227

3229-
| SynTypeDefnSimpleRepr.TypeAbbrev(ParserDetail.Ok, rhsType, m) ->
3228+
| SynTypeDefnSimpleRepr.TypeAbbrev(ParserDetail.Ok, rhsType, _m) ->
32303229

32313230
#if !NO_TYPEPROVIDERS
32323231
// Check we have not already decided that this is a generative provided type definition. If we have already done this (i.e. this is the second pass
@@ -3275,7 +3274,7 @@ module EstablishTypeDefinitionCores =
32753274

32763275
if not firstPass then
32773276
let ftyvs = freeInTypeLeftToRight g false ty
3278-
let typars = tycon.Typars m
3277+
let typars = tycon.Typars
32793278
if ftyvs.Length <> typars.Length then
32803279
errorR(Deprecated(FSComp.SR.tcTypeAbbreviationHasTypeParametersMissingOnType(), tycon.Range))
32813280

@@ -3300,9 +3299,8 @@ module EstablishTypeDefinitionCores =
33003299
match origInfo, tyconAndAttrsOpt with
33013300
| (typeDefCore, _, _), Some (tycon, (attrs, _)) ->
33023301
let (MutRecDefnsPhase1DataForTycon(_, synTyconRepr, explicitImplements, _, _, _)) = typeDefCore
3303-
let m = tycon.Range
33043302
let tcref = mkLocalTyconRef tycon
3305-
let envinner = AddDeclaredTypars CheckForDuplicateTypars (tycon.Typars m) envinner
3303+
let envinner = AddDeclaredTypars CheckForDuplicateTypars (tycon.Typars) envinner
33063304
let envinner = MakeInnerEnvForTyconRef envinner tcref false
33073305

33083306
let implementedTys, _ = List.mapFold (mapFoldFst (TcTypeAndRecover cenv NoNewTypars checkConstraints ItemOccurrence.UseInType WarnOnIWSAM.No envinner)) tpenv explicitImplements
@@ -3463,7 +3461,7 @@ module EstablishTypeDefinitionCores =
34633461
if allowed then
34643462
if kind = explicitKind then
34653463
warning(PossibleUnverifiableCode m)
3466-
elif List.isEmpty (thisTyconRef.Typars m) then
3464+
elif List.isEmpty (thisTyconRef.Typars) then
34673465
errorR (Error(FSComp.SR.tcOnlyStructsCanHaveStructLayout(), m))
34683466
else
34693467
errorR (Error(FSComp.SR.tcGenericTypesCannotHaveStructLayout(), m))
@@ -3495,7 +3493,7 @@ module EstablishTypeDefinitionCores =
34953493
if not ctorArgNames.IsEmpty then
34963494
errorR (Error(FSComp.SR.parsOnlyClassCanTakeValueArguments(), pat.Range))
34973495

3498-
let envinner = AddDeclaredTypars CheckForDuplicateTypars (tycon.Typars m) envinner
3496+
let envinner = AddDeclaredTypars CheckForDuplicateTypars (tycon.Typars) envinner
34993497
let envinner = MakeInnerEnvForTyconRef envinner thisTyconRef false
35003498

35013499
let multiCaseUnionStructCheck (unionCases: UnionCase list) =
@@ -3661,7 +3659,7 @@ module EstablishTypeDefinitionCores =
36613659
writeFakeRecordFieldsToSink userFields
36623660

36633661
let superTy = tycon.TypeContents.tcaug_super
3664-
let containerInfo = TyconContainerInfo(innerParent, thisTyconRef, thisTyconRef.Typars m, NoSafeInitInfo)
3662+
let containerInfo = TyconContainerInfo(innerParent, thisTyconRef, thisTyconRef.Typars, NoSafeInitInfo)
36653663
let kind = InferTyconKind g (kind, attrs, slotsigs, fields, inSig, isConcrete, m)
36663664
match kind with
36673665
| SynTypeDefnKind.Opaque ->
@@ -3733,7 +3731,7 @@ module EstablishTypeDefinitionCores =
37333731
let _, _, curriedArgInfos, returnTy, _ = GetValReprTypeInCompiledForm g (arity |> TranslateSynValInfo cenv m (TcAttributes cenv envinner) |> TranslatePartialValReprInfo []) 0 tyR m
37343732
if curriedArgInfos.Length < 1 then error(Error(FSComp.SR.tcInvalidDelegateSpecification(), m))
37353733
if curriedArgInfos.Length > 1 then error(Error(FSComp.SR.tcDelegatesCannotBeCurried(), m))
3736-
let ttps = thisTyconRef.Typars m
3734+
let ttps = thisTyconRef.Typars
37373735
let fparams =
37383736
curriedArgInfos.Head
37393737
|> List.map (fun (ty, argInfo: ArgReprInfo) ->
@@ -4049,7 +4047,7 @@ module EstablishTypeDefinitionCores =
40494047
let (MutRecDefnsPhase1DataForTycon(synTyconInfo, _, _, _, _, _)) = typeDefCore
40504048
let (SynComponentInfo(_, TyparsAndConstraints (_, cs1), cs2, _, _, _, _, _)) = synTyconInfo
40514049
let synTyconConstraints = cs1 @ cs2
4052-
let envForTycon = AddDeclaredTypars CheckForDuplicateTypars (tycon.Typars m) envForDecls
4050+
let envForTycon = AddDeclaredTypars CheckForDuplicateTypars (tycon.Typars) envForDecls
40534051
let thisTyconRef = mkLocalTyconRef tycon
40544052
let envForTycon = MakeInnerEnvForTyconRef envForTycon thisTyconRef false
40554053
try
@@ -4170,7 +4168,7 @@ module EstablishTypeDefinitionCores =
41704168

41714169
// No inferred constraints allowed on declared typars
41724170
(envMutRecPrelim, withEnvs) ||> MutRecShapes.iterTyconsWithEnv (fun envForDecls (_, tyconOpt) ->
4173-
tyconOpt |> Option.iter (fun tycon -> tycon.Typars m |> List.iter (SetTyparRigid envForDecls.DisplayEnv m)))
4171+
tyconOpt |> Option.iter (fun tycon -> tycon.Typars |> List.iter (SetTyparRigid envForDecls.DisplayEnv m)))
41744172

41754173
// Phase1E. OK, now recheck the abbreviations, super/interface and explicit constraints types (this time checking constraints)
41764174
(envMutRecPrelim, withAttrs) ||> MutRecShapes.iterTyconsWithEnv (fun envForDecls (origInfo, tyconAndAttrsOpt) ->
@@ -4273,7 +4271,7 @@ module TcDeclarations =
42734271
tcref.Deref.IsFSharpDelegateTycon ||
42744272
tcref.Deref.IsFSharpEnumTycon
42754273

4276-
let reqTypars = tcref.Typars m
4274+
let reqTypars = tcref.Typars
42774275

42784276
// Member definitions are intrinsic (added directly to the type) if:
42794277
// a) For interfaces, only if it is in the original defn.

src/Compiler/Checking/CheckIncrementalClasses.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ type IncrClassReprInfo =
503503
let ctorDeclaredTypars = staticCtorInfo.GetNormalizedIncrCtorDeclaredTypars cenv denv staticCtorInfo.TyconRef.Range
504504

505505
// Note: tcrefObjTy contains the original "formal" typars, thisTy is the "fresh" one... f<>fresh.
506-
let revTypeInst = List.zip ctorDeclaredTypars (tcref.TyparsNoRange |> List.map mkTyparTy)
506+
let revTypeInst = List.zip ctorDeclaredTypars (tcref.Typars |> List.map mkTyparTy)
507507

508508
yield MakeIncrClassField(localRep.RepInfoTcGlobals, cpath, revTypeInst, v, isStatic, rfref)
509509
| _ ->

src/Compiler/Checking/CheckPatterns.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ and TcRecordPat warnOnUpper (cenv: cenv) env vFlags patEnv ty fieldPats m =
510510
| Some(tinst, tcref, fldsmap, _fldsList) ->
511511

512512
let gtyp = mkWoNullAppTy tcref tinst
513-
let inst = List.zip (tcref.Typars m) tinst
513+
let inst = List.zip (tcref.Typars) tinst
514514

515515
UnifyTypes cenv env m ty gtyp
516516

@@ -658,7 +658,7 @@ and ApplyUnionCaseOrExn m (cenv: cenv) env overallTy item =
658658
CheckUnionCaseAttributes g ucref m |> CommitOperationResult
659659
CheckUnionCaseAccessible cenv.amap m ad ucref |> ignore
660660
let resTy = actualResultTyOfUnionCase ucinfo.TypeInst ucref
661-
let inst = mkTyparInst ucref.TyconRef.TyparsNoRange ucinfo.TypeInst
661+
let inst = mkTyparInst ucref.TyconRef.Typars ucinfo.TypeInst
662662
let mkf =
663663
try
664664
UnifyTypes cenv env m overallTy resTy

0 commit comments

Comments
 (0)