Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow parameter-less CustomOperation #16475

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Compiler/Checking/AttributeChecking.fs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ let TryBindMethInfoAttribute g (m: range) (AttribInfo(atref, _) as attribSpec) m
(fun provAttribs ->
match provAttribs.PUntaint((fun a -> a.GetAttributeConstructorArgs(provAttribs.TypeProvider.PUntaintNoFailure(id), atref.FullName)), m) with
| Some args -> f3 args
| None -> None)
| None -> None)
#else
(fun _provAttribs -> None)
#endif
Expand Down
18 changes: 13 additions & 5 deletions src/Compiler/Checking/CheckComputationExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -266,14 +266,22 @@ let TcComputationExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (mWhol
/// Decide if the builder is an auto-quote builder
let isAutoQuote = hasMethInfo "Quote"

let customOperationMethods =
let customOperationMethods =
AllMethInfosOfTypeInScope ResultCollectionSettings.AllResults cenv.infoReader env.NameEnv None ad IgnoreOverrides mBuilderVal builderTy
|> List.choose (fun methInfo ->
|> List.choose (fun methInfo ->
if not (IsMethInfoAccessible cenv.amap mBuilderVal ad methInfo) then None else
let nameSearch =
TryBindMethInfoAttribute cenv.g mBuilderVal cenv.g.attrib_CustomOperationAttribute methInfo
let nameSearch =
TryBindMethInfoAttribute cenv.g mBuilderVal cenv.g.attrib_CustomOperationAttribute methInfo
IgnoreAttribute // We do not respect this attribute for IL methods
(function Attrib(_, _, [ AttribStringArg msg ], _, _, _, _) -> Some msg | _ -> None)
(fun attr ->
match attr with
| Attrib(_, _, [ AttribStringArg msg ], _, _, _, _) when msg = "" ->
Some methInfo.LogicalName
| Attrib(_, _, [ ], _, _, _, _) ->
Some methInfo.LogicalName
| Attrib(_, _, [ AttribStringArg msg ], _, _, _, _) ->
Some msg
| _ -> None)
IgnoreAttribute // We do not respect this attribute for provided methods

match nameSearch with
Expand Down
1 change: 1 addition & 0 deletions src/FSharp.Core/prim-types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ namespace Microsoft.FSharp.Core
let mutable maintainsVarSpace = false
let mutable maintainsVarSpaceWithBind = false
let mutable joinOnWord = ""
new() = CustomOperationAttribute("")
member _.Name = name
member _.AllowIntoPattern with get() = allowInto and set v = allowInto <- v
member _.IsLikeZip with get() = isBinary and set v = isBinary <- v
Expand Down
4 changes: 4 additions & 0 deletions src/FSharp.Core/prim-types.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@ namespace Microsoft.FSharp.Core
/// <returns>CustomOperationAttribute</returns>
new: name:string -> CustomOperationAttribute

/// <summary>Create an instance of attribute with empty name</summary>
/// <returns>CustomOperationAttribute</returns>
new: unit -> CustomOperationAttribute

/// <summary>Get the name of the custom operation when used in a query or other computation expression</summary>
member Name: string

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace Conformance.Expressions.ComputationExpressions

open Xunit
open FSharp.Test.Compiler

module CustomOperations =

// it becomes increasingly difficult to use packaged fslib in tests.
#if !FSHARPCORE_USE_PACKAGE
[<Fact>]
#endif
let ``[<CustomOperation>] without explicit name is allowed, uses method name as operation name`` () =
FSharp """
module CustomOperationTest
type CBuilder() =
[<CustomOperation>]
member this.Foo _ = "Foo"
[<CustomOperation>]
member this.foo _ = "foo"
member this.Yield _ = ()
member this.Zero _ = ()


[<EntryPoint>]
let main _ =
let cb = CBuilder()

let x = cb { Foo }
let y = cb { foo }
printfn $"{x}"
printfn $"{y}"

if x <> "Foo" then
failwith "not Foo"
if y <> "foo" then
failwith "not foo"
0
"""
|> asExe
|> compileAndRun
|> shouldSucceed
Original file line number Diff line number Diff line change
Expand Up @@ -31,53 +31,77 @@
<Link>FsUnit.fs</Link>
</Compile>
<Compile Include="Conformance\BasicGrammarElements\AccessibilityAnnotations\Basic\Basic.fs" />
<Compile Include="Conformance\BasicGrammarElements\AccessibilityAnnotations\OnOverridesAndIFaceImpl\OnOverridesAndIFaceImpl.fs" />
<Compile Include="Conformance\BasicGrammarElements\AccessibilityAnnotations\OnTypeMembers\OnTypeMembers.fs" />
<Compile Include="Conformance\BasicGrammarElements\AccessibilityAnnotations\PermittedLocations\PermittedLocations.fs" />
<Compile Include="Conformance\BasicGrammarElements\CustomAttributes\AttributeInheritance\AttributeInheritance.fs" />
<Compile Include="Conformance\BasicGrammarElements\CustomAttributes\AttributeUsage\AttributeUsage.fs" />
<Compile
Include="Conformance\BasicGrammarElements\AccessibilityAnnotations\OnOverridesAndIFaceImpl\OnOverridesAndIFaceImpl.fs" />
<Compile
Include="Conformance\BasicGrammarElements\AccessibilityAnnotations\OnTypeMembers\OnTypeMembers.fs" />
<Compile
Include="Conformance\BasicGrammarElements\AccessibilityAnnotations\PermittedLocations\PermittedLocations.fs" />
<Compile
Include="Conformance\BasicGrammarElements\CustomAttributes\AttributeInheritance\AttributeInheritance.fs" />
<Compile
Include="Conformance\BasicGrammarElements\CustomAttributes\AttributeUsage\AttributeUsage.fs" />
<Compile Include="Conformance\BasicGrammarElements\CustomAttributes\Basic\Basic.fs" />
<Compile Include="Conformance\BasicGrammarElements\CustomAttributes\ImportedAttributes\ImportedAttributes.fs" />
<Compile Include="Conformance\BasicGrammarElements\CustomAttributes\ArgumentsOfAllTypes\ArgumentsOfAllTypes.fs" />
<Compile
Include="Conformance\BasicGrammarElements\CustomAttributes\ImportedAttributes\ImportedAttributes.fs" />
<Compile
Include="Conformance\BasicGrammarElements\CustomAttributes\ArgumentsOfAllTypes\ArgumentsOfAllTypes.fs" />
<Compile Include="Conformance\BasicGrammarElements\DelegateTypes\DelegateDefinition.fs" />
<Compile Include="Conformance\BasicGrammarElements\EntryPoint\EntryPoint.fs" />
<Compile Include="Conformance\BasicGrammarElements\Events\Basic\Basic.fs" />
<Compile Include="Conformance\BasicGrammarElements\ExceptionDefinitions\ExceptionDefinitions.fs" />
<Compile Include="Conformance\BasicGrammarElements\ExplicitObjectConstructors\ExplicitObjectConstructors.fs" />
<Compile
Include="Conformance\BasicGrammarElements\ExplicitObjectConstructors\ExplicitObjectConstructors.fs" />
<Compile Include="Conformance\BasicGrammarElements\FieldMembers\FieldMembers.fs" />
<Compile Include="Conformance\BasicGrammarElements\ImplicitObjectConstructors\ImplicitObjectConstructors.fs" />
<Compile
Include="Conformance\BasicGrammarElements\ImplicitObjectConstructors\ImplicitObjectConstructors.fs" />
<Compile Include="Conformance\BasicGrammarElements\ImportDeclarations\ImportDeclarations.fs" />
<Compile Include="Conformance\BasicGrammarElements\InterfaceSpecificationsAndImplementations\InterfaceSpecificationsAndImplementations.fs" />
<Compile
Include="Conformance\BasicGrammarElements\InterfaceSpecificationsAndImplementations\InterfaceSpecificationsAndImplementations.fs" />
<Compile Include="Conformance\BasicGrammarElements\LetBindings\Basic\Basic.fs" />
<Compile Include="Conformance\BasicGrammarElements\LetBindings\TypeFunctions\TypeFunctions.fs" />
<Compile Include="Conformance\BasicGrammarElements\LetBindings\ActivePatternBindings\ActivePatternBindings.fs" />
<Compile Include="Conformance\BasicGrammarElements\LetBindings\ExplicitTypeParameters\ExplicitTypeParameters.fs" />
<Compile
Include="Conformance\BasicGrammarElements\LetBindings\ActivePatternBindings\ActivePatternBindings.fs" />
<Compile
Include="Conformance\BasicGrammarElements\LetBindings\ExplicitTypeParameters\ExplicitTypeParameters.fs" />
<Compile Include="Conformance\BasicGrammarElements\MemberDefinitions\MemberDefinitions.fs" />
<Compile Include="Conformance\BasicGrammarElements\MemberDefinitions\ImplementingDispatchSlots\ImplementingDispatchSlots.fs" />
<Compile Include="Conformance\BasicGrammarElements\MemberDefinitions\MethodsAndProperties\MethodsAndProperties.fs" />
<Compile Include="Conformance\BasicGrammarElements\MemberDefinitions\NamedArguments\NamedArguments.fs" />
<Compile Include="Conformance\BasicGrammarElements\MemberDefinitions\OptionalArguments\OptionalArguments.fs" />
<Compile Include="Conformance\BasicGrammarElements\MemberDefinitions\OptionalDefaultParamArgs\OptionalDefaultParamArgs.fs" />
<Compile Include="Conformance\BasicGrammarElements\MemberDefinitions\OverloadingMembers\OverloadingMembers.fs" />
<Compile
Include="Conformance\BasicGrammarElements\MemberDefinitions\ImplementingDispatchSlots\ImplementingDispatchSlots.fs" />
<Compile
Include="Conformance\BasicGrammarElements\MemberDefinitions\MethodsAndProperties\MethodsAndProperties.fs" />
<Compile
Include="Conformance\BasicGrammarElements\MemberDefinitions\NamedArguments\NamedArguments.fs" />
<Compile
Include="Conformance\BasicGrammarElements\MemberDefinitions\OptionalArguments\OptionalArguments.fs" />
<Compile
Include="Conformance\BasicGrammarElements\MemberDefinitions\OptionalDefaultParamArgs\OptionalDefaultParamArgs.fs" />
<Compile
Include="Conformance\BasicGrammarElements\MemberDefinitions\OverloadingMembers\OverloadingMembers.fs" />
<Compile Include="Conformance\BasicGrammarElements\MethodResolution.fs" />
<Compile Include="Conformance\BasicGrammarElements\ModuleAbbreviations\ModuleAbbreviations.fs" />
<Compile Include="Conformance\BasicGrammarElements\ModuleDefinitions\ModuleDefinitions.fs" />
<Compile Include="Conformance\BasicGrammarElements\NamespaceDeclGroups\NamespaceDeclGroups.fs" />
<Compile Include="Conformance\BasicGrammarElements\NullRepresentations\NullRepresentations.fs" />
<Compile Include="Conformance\BasicGrammarElements\OperatorNames\OperatorNames.fs" />
<Compile Include="Conformance\BasicGrammarElements\PrecedenceAndOperators\PrecedenceAndOperators.fs" />
<Compile
Include="Conformance\BasicGrammarElements\PrecedenceAndOperators\PrecedenceAndOperators.fs" />
<Compile Include="Conformance\BasicGrammarElements\StaticLet\StaticLetInUnionsAndRecords.fs" />
<Compile Include="Conformance\BasicGrammarElements\TypeAbbreviations\TypeAbbreviations.fs" />
<Compile Include="Conformance\BasicGrammarElements\TypeAbbreviations\WarnForAutoOpenAttributeAlias.fs" />
<Compile
Include="Conformance\BasicGrammarElements\TypeAbbreviations\WarnForAutoOpenAttributeAlias.fs" />
<Compile Include="Conformance\BasicGrammarElements\ValueRestriction\ValueRestriction.fs" />
<Compile Include="Conformance\BasicGrammarElements\UseBindings\UseBindings.fs" />
<Compile Include="Conformance\Constraints\Unmanaged.fs" />
<Compile Include="Conformance\GeneratedEqualityHashingComparison\Attributes\Diags\Attributes_Diags.fs" />
<Compile Include="Conformance\GeneratedEqualityHashingComparison\Attributes\Legacy\Attributes_Legacy.fs" />
<Compile Include="Conformance\Constraints\Unmanaged.fs" />
<Compile
Include="Conformance\GeneratedEqualityHashingComparison\Attributes\Diags\Attributes_Diags.fs" />
<Compile
Include="Conformance\GeneratedEqualityHashingComparison\Attributes\Legacy\Attributes_Legacy.fs" />
<Compile Include="Conformance\GeneratedEqualityHashingComparison\Basic\Basic.fs" />
<Compile Include="Conformance\GeneratedEqualityHashingComparison\IComparison\IComparison.fs" />
<Compile Include="Conformance\Expressions\ApplicationExpressions\BasicApplication\BasicApplication.fs" />
<Compile
Include="Conformance\Expressions\ApplicationExpressions\BasicApplication\BasicApplication.fs" />
<Compile Include="Conformance\Expressions\BindingExpressions\BindingExpressions.fs" />
<Compile Include="Conformance\Expressions\ComputationExpressions\CustomOperations.fs" />
<Compile Include="Conformance\Expressions\ObjectExpressions\ObjectExpressions.fs" />
<Compile Include="Conformance\Expressions\ControlFlowExpressions\PatternMatching\PatternMatching.fs" />
<Compile Include="Conformance\Expressions\ControlFlowExpressions\SequenceIteration\SequenceIteration.fs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>preview</LangVersion>
<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
</PropertyGroup>

<PropertyGroup>
<DisableAutoSetFscCompilerPath>true</DisableAutoSetFscCompilerPath>
<DotnetFscCompilerPath>$(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Debug/net8.0/fsc.dll</DotnetFscCompilerPath>
<Fsc_DotNET_DotnetFscCompilerPath>$(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Debug/net8.0/fsc.dll</Fsc_DotNET_DotnetFscCompilerPath>
<FSharpPreferNetFrameworkTools>False</FSharpPreferNetFrameworkTools>
<FSharpPrefer64BitTools>True</FSharpPrefer64BitTools>
</PropertyGroup>

<ItemGroup>
<Reference Include="$(MSBuildThisFileDirectory)../../../artifacts/bin/FSharp.Core/Debug/netstandard2.0/FSharp.Core.dll" />
<Compile Include="Program.fs" />
</ItemGroup>

</Project>
25 changes: 25 additions & 0 deletions tests/projects/Sample_Local_Compiler_and_FSLib/Program.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module Program

type CBuilder() =
[<CustomOperation>]
member this.Foo _ = "Foo"
[<CustomOperation>]
member this.foo _ = "foo"
member this.Yield _ = ()
member this.Zero _ = ()


[<EntryPoint>]
let main _ =
let cb = CBuilder()

let x = cb { Foo }
let y = cb { foo }
printfn $"{x}"
printfn $"{y}"

if x <> "Foo" then
failwith "not Foo"
if y <> "foo" then
failwith "not foo"
0
Loading