Skip to content

Commit b645ace

Browse files
tbobyT-Gro
andauthored
Allow _.Property / _.MethodCall() / _.IndexerAccess[idx] shorthand for accessor functions (#13907)
Co-authored-by: Tomas Grosup <[email protected]>
1 parent 5c2dc44 commit b645ace

File tree

52 files changed

+702
-20
lines changed

Some content is hidden

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

52 files changed

+702
-20
lines changed

src/Compiler/Checking/CheckExpressions.fs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5525,7 +5525,15 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE
55255525
TcNonControlFlowExpr env <| fun env ->
55265526
CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy.Commit, env.AccessRights)
55275527
TcConstExpr cenv overallTy env m tpenv synConst
5528-
5528+
| SynExpr.DotLambda (synExpr, m, trivia) ->
5529+
if env.NameEnv.eUnqualifiedItems |> Map.containsKey "_arg1"
5530+
then
5531+
warning(Error(FSComp.SR.tcAmbiguousDiscardDotLambda(), trivia.UnderscoreRange))
5532+
let unaryArg = mkSynId trivia.UnderscoreRange (cenv.synArgNameGenerator.New())
5533+
let svar = mkSynCompGenSimplePatVar unaryArg
5534+
let pushedExpr = pushUnaryArg synExpr unaryArg
5535+
let lambda = SynExpr.Lambda(false, false, SynSimplePats.SimplePats([ svar ],[], svar.Range), pushedExpr, None, m, SynExprLambdaTrivia.Zero)
5536+
TcIteratedLambdas cenv true env overallTy Set.empty tpenv lambda
55295537
| SynExpr.Lambda _ ->
55305538
TcIteratedLambdas cenv true env overallTy Set.empty tpenv synExpr
55315539

@@ -8722,6 +8730,7 @@ and TcImplicitOpItemThen (cenv: cenv) overallTy env id sln tpenv mItem delayed =
87228730
| SynExpr.Const _
87238731
| SynExpr.Typar _
87248732
| SynExpr.LongIdent _
8733+
| SynExpr.DotLambda _
87258734
| SynExpr.Dynamic _ -> true
87268735

87278736
| SynExpr.Tuple (_, synExprs, _, _)

src/Compiler/Checking/MethodCalls.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,7 @@ let InferLambdaArgsForLambdaPropagation origRhsExpr =
841841
match e with
842842
| SynExpr.Lambda (body = rest) -> 1 + loop rest
843843
| SynExpr.MatchLambda _ -> 1
844+
| SynExpr.DotLambda _ -> 1
844845
| _ -> 0
845846
loop origRhsExpr
846847

src/Compiler/Driver/GraphChecking/FileContentMapping.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ let visitSynExpr (e: SynExpr) : FileContentEntry list =
362362
| SynExpr.IndexFromEnd (expr, _) -> visit expr continuation
363363
| SynExpr.ComputationExpr (expr = expr) -> visit expr continuation
364364
| SynExpr.Lambda (args = args; body = body) -> visit body (fun bodyNodes -> visitSynSimplePats args @ bodyNodes |> continuation)
365+
| SynExpr.DotLambda (expr = expr) -> visit expr continuation
365366
| SynExpr.MatchLambda (matchClauses = clauses) -> List.collect visitSynMatchClause clauses |> continuation
366367
| SynExpr.Match (expr = expr; clauses = clauses) ->
367368
visit expr (fun exprNodes ->

src/Compiler/FSComp.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,6 +1701,9 @@ featureStaticLetInRecordsDusEmptyTypes,"Allow static let bindings in union, reco
17011701
3566,tcMultipleRecdTypeChoice,"Multiple type matches were found:\n%s\nThe type '%s' was used. Due to the overlapping field names\n%s\nconsider using type annotations or change the order of open statements."
17021702
3567,parsMissingMemberBody,"Expecting member body"
17031703
3568,parsMissingKeyword,"Missing keyword '%s'"
1704+
3570,tcAmbiguousDiscardDotLambda,"The meaning of _ is ambiguous here. It cannot be used for a discarded variable and a function shorthand in the same scope."
1705+
3571,parsUnderScoreDotLambdaNonAtomic," _. shorthand syntax for lambda functions can only be used with atomic expressions. That means expressions with no whitespace unless enclosed in parentheses."
1706+
featureAccessorFunctionShorthand,"underscore dot shorthand for accessor only function"
17041707
3569,chkNotTailRecursive,"The member or function '%s' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way."
17051708
3570,tcStaticBindingInExtrinsicAugmentation,"Static bindings cannot be added to extrinsic augmentations. Consider using a 'static member' instead."
17061709
3571,pickleFsharpCoreBackwardsCompatible,"Newly added pickle state cannot be used in FSharp.Core, since it must be working in older compilers+tooling as well. The time window is at least 3 years after feature introduction. Violation: %s . Context: \n %s "

src/Compiler/Facilities/LanguageFeatures.fs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ type LanguageFeature =
5555
| LowercaseDUWhenRequireQualifiedAccess
5656
| InterfacesWithAbstractStaticMembers
5757
| SelfTypeConstraints
58+
| AccessorFunctionShorthand
5859
| MatchNotAllowedForUnionCaseWithNoData
5960
| CSharpExtensionAttributeNotRequired
6061
| ErrorForNonVirtualMembersOverrides
@@ -150,6 +151,7 @@ type LanguageVersion(versionText) =
150151

151152
// F# preview
152153
LanguageFeature.FromEndSlicing, previewVersion
154+
LanguageFeature.AccessorFunctionShorthand, previewVersion
153155
LanguageFeature.MatchNotAllowedForUnionCaseWithNoData, previewVersion
154156
LanguageFeature.CSharpExtensionAttributeNotRequired, previewVersion
155157
LanguageFeature.ErrorForNonVirtualMembersOverrides, previewVersion
@@ -275,6 +277,7 @@ type LanguageVersion(versionText) =
275277
| LanguageFeature.LowercaseDUWhenRequireQualifiedAccess -> FSComp.SR.featureLowercaseDUWhenRequireQualifiedAccess ()
276278
| LanguageFeature.InterfacesWithAbstractStaticMembers -> FSComp.SR.featureInterfacesWithAbstractStaticMembers ()
277279
| LanguageFeature.SelfTypeConstraints -> FSComp.SR.featureSelfTypeConstraints ()
280+
| LanguageFeature.AccessorFunctionShorthand -> FSComp.SR.featureAccessorFunctionShorthand ()
278281
| LanguageFeature.MatchNotAllowedForUnionCaseWithNoData -> FSComp.SR.featureMatchNotAllowedForUnionCaseWithNoData ()
279282
| LanguageFeature.CSharpExtensionAttributeNotRequired -> FSComp.SR.featureCSharpExtensionAttributeNotRequired ()
280283
| LanguageFeature.ErrorForNonVirtualMembersOverrides -> FSComp.SR.featureErrorForNonVirtualMembersOverrides ()

src/Compiler/Facilities/LanguageFeatures.fsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type LanguageFeature =
4545
| LowercaseDUWhenRequireQualifiedAccess
4646
| InterfacesWithAbstractStaticMembers
4747
| SelfTypeConstraints
48+
| AccessorFunctionShorthand
4849
| MatchNotAllowedForUnionCaseWithNoData
4950
| CSharpExtensionAttributeNotRequired
5051
| ErrorForNonVirtualMembersOverrides

src/Compiler/Service/FSharpParseFileResults.fs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,8 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput,
292292
// Capture the body of a lambda, often nested in a call to a collection function
293293
| SynExpr.Lambda (body = body) when rangeContainsPos body.Range pos -> getIdentRangeForFuncExprInApp traverseSynExpr body pos
294294

295+
| SynExpr.DotLambda (expr = body) when rangeContainsPos body.Range pos -> getIdentRangeForFuncExprInApp traverseSynExpr body pos
296+
295297
| SynExpr.Do (expr, range) when rangeContainsPos range pos -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos
296298

297299
| SynExpr.Assert (expr, range) when rangeContainsPos range pos -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos
@@ -425,6 +427,7 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput,
425427
override _.VisitBinding(_path, defaultTraverse, binding) =
426428
match binding with
427429
| SynBinding(expr = SynExpr.Lambda _) when skipLambdas -> defaultTraverse binding
430+
| SynBinding(expr = SynExpr.DotLambda _) when skipLambdas -> defaultTraverse binding
428431

429432
// Skip manually type-annotated bindings
430433
| SynBinding(returnInfo = Some (SynBindingReturnInfo _)) -> defaultTraverse binding
@@ -533,6 +536,7 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput,
533536
| SynBinding.SynBinding (expr = expr; range = range) when Position.posEq range.Start pos ->
534537
match expr with
535538
| SynExpr.Lambda _ -> Some range
539+
| SynExpr.DotLambda _ -> Some range
536540
| _ -> None
537541
| _ -> defaultTraverse binding
538542
}
@@ -667,6 +671,7 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput,
667671
match expr with
668672
| SynExpr.ArbitraryAfterError _
669673
| SynExpr.LongIdent _
674+
| SynExpr.DotLambda _
670675
| SynExpr.LibraryOnlyILAssembly _
671676
| SynExpr.LibraryOnlyStaticOptimization _
672677
| SynExpr.Null _
@@ -828,6 +833,8 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput,
828833

829834
| SynExpr.Lambda (body = bodyExpr) -> yield! walkExpr true bodyExpr
830835

836+
| SynExpr.DotLambda (expr = bodyExpr) -> yield! walkExpr true bodyExpr
837+
831838
| SynExpr.Match (matchDebugPoint = spBind; expr = inpExpr; clauses = cl) ->
832839
yield! walkBindSeqPt spBind
833840
yield! walkExpr false inpExpr

src/Compiler/Service/ServiceInterfaceStubGenerator.fs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,8 @@ module InterfaceStubGenerator =
880880

881881
| SynExpr.Lambda (body = synExpr) -> walkExpr synExpr
882882

883+
| SynExpr.DotLambda (expr = synExpr) -> walkExpr synExpr
884+
883885
| SynExpr.MatchLambda (_isExnMatch, _argm, synMatchClauseList, _spBind, _wholem) ->
884886
synMatchClauseList
885887
|> List.tryPick (fun (SynMatchClause (resultExpr = e)) -> walkExpr e)

src/Compiler/Service/ServiceParseTreeWalk.fs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,8 @@ module SyntaxTraversal =
561561
| None -> traverseSynExpr synExpr
562562
| x -> x
563563

564+
| SynExpr.DotLambda (expr = e) -> traverseSynExpr e
565+
564566
| SynExpr.MatchLambda (_isExnMatch, _argm, synMatchClauseList, _spBind, _wholem) ->
565567
synMatchClauseList
566568
|> List.map (fun x -> dive x x.Range (traverseSynMatchClause path))

src/Compiler/Service/ServiceParsedInputOps.fs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,8 @@ module ParsedInput =
752752

753753
| SynExpr.Lambda (body = e) -> walkExprWithKind parentKind e
754754

755+
| SynExpr.DotLambda (expr = e) -> walkExprWithKind parentKind e
756+
755757
| SynExpr.MatchLambda (_, _, synMatchClauseList, _, _) -> List.tryPick walkClause synMatchClauseList
756758

757759
| SynExpr.Match (expr = e; clauses = synMatchClauseList) ->
@@ -1739,6 +1741,7 @@ module ParsedInput =
17391741
| SynExpr.Lambda (args = pats; body = e) ->
17401742
walkSimplePats pats
17411743
walkExpr e
1744+
| SynExpr.DotLambda (expr = e) -> walkExpr e
17421745
| SynExpr.New (_, t, e, _)
17431746
| SynExpr.TypeTest (e, t, _)
17441747
| SynExpr.Upcast (e, t, _)

0 commit comments

Comments
 (0)